RepoPilotOpen in app →

ynqa/jnv

Interactive JSON filter using jq

Mixed

Solo project — review before adopting

weakest axis
Use as dependencyMixed

single-maintainer (no co-maintainers visible); no tests detected

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 5w ago
  • MIT licensed
  • CI configured
Show all 5 evidence items →
  • Solo or near-solo (1 contributor active in recent commits)
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: onboard a second core maintainer

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/ynqa/jnv?axis=fork)](https://repopilot.app/r/ynqa/jnv)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/ynqa/jnv on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: ynqa/jnv

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/ynqa/jnv shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Solo project — review before adopting

  • Last commit 5w ago
  • MIT licensed
  • CI configured
  • ⚠ Solo or near-solo (1 contributor active in recent commits)
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live ynqa/jnv repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/ynqa/jnv.

What it runs against: a local clone of ynqa/jnv — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in ynqa/jnv | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 65 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>ynqa/jnv</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of ynqa/jnv. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/ynqa/jnv.git
#   cd jnv
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of ynqa/jnv and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "ynqa/jnv(\\.git)?\\b" \\
  && ok "origin remote is ynqa/jnv" \\
  || miss "origin remote is not ynqa/jnv (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "src/main.rs" \\
  && ok "src/main.rs" \\
  || miss "missing critical file: src/main.rs"
test -f "src/json_viewer.rs" \\
  && ok "src/json_viewer.rs" \\
  || miss "missing critical file: src/json_viewer.rs"
test -f "src/query_editor.rs" \\
  && ok "src/query_editor.rs" \\
  || miss "missing critical file: src/query_editor.rs"
test -f "src/event_dispatcher.rs" \\
  && ok "src/event_dispatcher.rs" \\
  || miss "missing critical file: src/event_dispatcher.rs"
test -f "src/json.rs" \\
  && ok "src/json.rs" \\
  || miss "missing critical file: src/json.rs"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 65 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~35d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/ynqa/jnv"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

jnv is an interactive JSON viewer and jq filter editor written in Rust that runs in the terminal. It provides real-time syntax highlighting, jq filter evaluation using jaq, and auto-completion for JSON paths—eliminating the need for users to pre-install jq separately. It can consume JSON from files, stdin, or multiple JSON structures (JSON Lines format) and outputs the filtered result. Monolithic binary architecture: src/main.rs orchestrates the TUI, src/query_editor.rs handles jq filter input, src/json_viewer.rs renders the JSON tree, src/json.rs manages data, and src/config/ loads TOML-based configuration. src/runtime_tasks.rs and event_dispatcher.rs coordinate async event handling via tokio. The tool chains user input → jaq filter → filtered JSON display in a single event loop.

👥Who it's for

DevOps engineers, data engineers, and CLI power users who need to explore and filter JSON data interactively without switching between a text editor and jq. Developers building pipelines with JSON APIs who want immediate feedback on filter expressions without running separate jq commands.

🌱Maturity & risk

Actively maintained (v0.7.1). The project has CI/CD workflows (.github/workflows/ci.yml, release.yml), proper Dockerfile support, and is distributed across Homebrew, MacPorts, conda-forge, and Nix. However, the relatively small codebase (~76KB Rust) and lack of visible issue/PR details suggest it's a focused single-purpose tool rather than a massive ecosystem project.

Low risk: single Rust author (ynqa) but the project is actively maintained with release automation. Dependencies are well-established (tokio, serde, clap); jaq is the only domain-specific external jq implementation. No breaking changes evident. Primary risk is single-maintainer dependency for bug fixes, but the tool's scope is narrow and stable.

Active areas of work

No explicit PR or milestone data visible in the file list. The codebase appears stable with recent maintenance (v0.7.1 recently versioned). Focus areas inferred from code structure: debounce/animation performance tuning (src/utils/debounce.rs), keybind customization (default.toml), and completion accuracy (src/completion.rs).

🚀Get running

git clone https://github.com/ynqa/jnv.git
cd jnv
cargo build --release
./target/release/jnv --help
cat data.json | ./target/release/jnv
# Or install via cargo
cargo install jnv
jnv data.json

Daily commands:

cargo run -- <file.json>
# or with stdin
cat data.json | cargo run
# with Docker
docker build -t jnv .
docker run -it --rm -v $(pwd)/data.json:/jnv/data.json jnv /jnv/data.json

🗺️Map of the codebase

  • src/main.rs — Application entry point; orchestrates CLI argument parsing, configuration loading, and runtime initialization for the interactive JSON viewer.
  • src/json_viewer.rs — Core UI rendering engine for the interactive JSON viewer; handles display state, navigation, and layout of the JSON tree.
  • src/query_editor.rs — JQ filter editor component; manages user input, syntax highlighting, and integration with the jaq evaluation engine.
  • src/event_dispatcher.rs — Central event loop and input handler; routes keyboard/mouse events to appropriate handlers and coordinates application state updates.
  • src/json.rs — JSON parsing and representation layer; handles multiple JSON structures, validation, and jaq filter application.
  • src/config.rs — Configuration system; loads TOML settings for keybinds, UI behavior, debounce times, and appearance from user's config directory.
  • Cargo.toml — Dependency manifest; declares critical runtime dependencies (jaq-core, tokio, termcfg, arboard) that enable jq filtering and TUI rendering.

🛠️How to make changes

Add a new keybind

  1. Define the keybind constant in src/config.rs under the Config struct or defaults (src/config.rs)
  2. Add a case in src/event_dispatcher.rs to match the new key and dispatch the corresponding action (src/event_dispatcher.rs)
  3. Document the keybind in default.toml so users can see and override it (default.toml)

Add a new configuration option

  1. Add a new field to the Config struct in src/config.rs with serde attributes (src/config.rs)
  2. Add the option to default.toml with a comment explaining its purpose (default.toml)
  3. Import and use the new config field in the relevant module (e.g., src/json_viewer.rs for UI styling) (src/context.rs)

Add a new UI component or overlay

  1. Create a new method in src/json_viewer.rs or create a new module (e.g., src/my_overlay.rs) to render the component (src/json_viewer.rs)
  2. Add a rendering condition in src/main.rs or the main render loop to call your component based on application state (src/main.rs)
  3. Handle input events for the new component in src/event_dispatcher.rs by checking the current UI mode (src/event_dispatcher.rs)

Integrate a new jq-related feature

  1. Extend JSON parsing or filter logic in src/json.rs using the jaq-core API (src/json.rs)
  2. Update src/context.rs to store any new state (e.g., filter history, macro definitions) (src/context.rs)
  3. Add UI display and keybind handling in src/query_editor.rs and src/event_dispatcher.rs (src/query_editor.rs)

🔧Why these technologies

  • jaq-core (jq filter engine) — Provides a fast, Rust-native jq implementation without requiring external jq binary; tightly integrated with serde JSON
  • tokio (async runtime) — Enables non-blocking I/O for stdin reading, debounced filter evaluation, and responsive TUI during long operations
  • termcfg + crossterm (TUI framework) — Cross-platform terminal control for syntax highlighting, raw mode input, and smooth cursor/layout management
  • arboard (clipboard) — Provides reliable cross-platform clipboard access (wayland-data-control support) for copying JSON values
  • clap (CLI parsing) — Declarative, derive-macro-based CLI argument parsing for file input, stdin modes, and optional config paths
  • TOML configuration — Human-readable config format for keybinds, debounce timings, UI styling, and editor behavior without requiring code recompilation

⚖️Trade-offs already made

  • Use jaq instead of spawning external jq process

    • Why: Embedding jaq-core eliminates subprocess overhead and installation dependency; faster filter evaluation
    • Consequence: Jaq implements a subset of jq; some advanced jq features may not be available; requires maintaining compatibility with jaq-core releases
  • Single-threaded event loop with debouncing instead of live re-evaluation

    • Why: Prevents UI thrashing and excessive jaq evaluations while user types; improves perceived responsiveness
    • Consequence: Filter result slightly lags user input (configurable delay); more complex state management for pending edits
  • TOML config file instead of CLI flags for all options

    • Why: Reduces CLI complexity, enables persistent user preferences, supports complex nested settings (keybinds, styling)
    • Consequence: Users must discover and edit config file; adds filesystem dependency on config directory; breaking changes require migration logic
  • Streaming JSON parsing for multiple objects

    • Why: Allows processing large JSON files and newline-delimited JSON without loading entire file into memory
    • Consequence: Requires careful state management for multiple roots; viewer must handle list-of-objects case separately

🚫Non-goals (don't propose these)

  • Does not execute arbitrary shell commands; jq filter evaluation only
  • Does not persist edited JSON to disk; read-only navigation and filtering
  • Does not support real-time remote data sources or live streaming JSON updates
  • Not a general-purpose jq replacement; complements jq as an interactive tool for exploration
  • Does not handle authentication or encrypted JSON payloads

🪤Traps & gotchas

  1. Config location: Uses dirs::config_dir() which is platform-specific (~/.config/jnv/ on Linux, ~/Library/Application Support/jnv/ on macOS); users may not know where to place custom configs. 2. Async task handling: stdout_redirect.rs suggests special handling for UNIX stdout capture (--writ flag); non-UNIX platforms may have different behavior. 3. jaq version lock: jaq-core 2.2.1 is pinned; upgrading may break filter compatibility or output format. 4. Debounce timing: Default debounce values in default.toml affect responsiveness; misconfiguration can feel laggy or overly eager.

🏗️Architecture

💡Concepts to learn

  • Stream Deserialization (serde_json::StreamDeserializer) — jnv uses StreamDeserializer to parse multiple JSON values from stdin/files (e.g., JSON Lines) without loading the entire file into memory, critical for handling large datasets
  • Debounce/Throttle in TUIs — jnv implements debouncing (src/utils/debounce.rs) to avoid re-evaluating jaq filters on every keystroke; essential for responsive interactive UIs without overwhelming the filter engine
  • Event-Driven Async Architecture (tokio) — jnv coordinates user input, filter updates, and file I/O using tokio's async runtime; src/event_dispatcher.rs models the pattern crucial for non-blocking TUI responsiveness
  • Syntax Highlighting in Terminal (ANSI codes) — jnv renders JSON with color codes via termcfg; understanding terminal capabilities (colors, bold, etc.) is needed to extend UI styling
  • jq Filter Language & Semantics — jnv's entire purpose is wrapping jq filters; understanding jq's pipe operator, array/object slicing, and function composition is essential for any feature work
  • Configuration as Code (TOML Schema Composition) — jnv loads default.toml as baseline then merges user config (src/config.rs); understanding schema override/merge patterns is key for adding new configuration options
  • Auto-Completion Heuristics — src/completion.rs implements path-based auto-completion (identity, object-index, array-index) by analyzing JSON structure; extending this requires understanding lexical scoping and type inference
  • stedolan/jq — The original jq tool that jnv wraps and extends with interactive filtering—essential reference for understanding jq filter semantics
  • 01mf02/jaq — The pure-Rust jq implementation (jaq-core, jaq-json, jaq-std) that jnv uses under the hood for filter evaluation without external jq dependency
  • simeji/jid — Interactive JSON drill-down tool in Go that inspired jnv's navigation-first UX approach
  • fiatjaf/jiq — Another interactive jq editor that influenced jnv's filter-editor-plus-viewer design pattern
  • atuinsh/atuin — Similar TUI-first tool built with Rust/tokio; useful reference for advanced event handling and config management patterns

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add integration tests for jaq filter execution in src/json.rs

The repo uses jaq-core, jaq-json, and jaq-std for filter execution, but there are no visible test files (no src/*.rs containing #[cfg(test)]). Given that jnv's core functionality is applying jq filters to JSON, comprehensive tests for edge cases (invalid filters, malformed JSON, complex filter chains) would prevent regressions and improve reliability for contributors adding filter features.

  • [ ] Create src/json_tests.rs or add #[cfg(test)] modules to src/json.rs
  • [ ] Add tests for successful filter parsing and execution with sample JSON inputs
  • [ ] Add tests for error cases (invalid jaq syntax, type mismatches, null inputs)
  • [ ] Add tests for complex filter chains combining multiple jaq operations
  • [ ] Integrate tests into CI by verifying .github/workflows/ci.yml runs cargo test

Add configuration validation and unit tests in src/config.rs

The config module (src/config.rs and src/config/duration.rs) loads TOML settings from default.toml and user configs, but there are no visible validation tests. Invalid configurations (negative debounce times, invalid animation speeds, malformed TOML) could crash the UI. Adding validation tests and error handling would catch config issues early and guide contributors on safe config patterns.

  • [ ] Add #[cfg(test)] test module to src/config.rs
  • [ ] Add tests for valid configuration parsing from the provided default.toml
  • [ ] Add tests for boundary conditions (zero/negative durations, max animation speeds)
  • [ ] Add tests for missing optional fields and defaults fallback behavior
  • [ ] Verify duration.rs parsing with edge cases (very large durations, invalid format strings)

Add snapshot tests for event_dispatcher.rs state transitions

The event_dispatcher.rs handles user interactions and state management, which is critical for the interactive UI. Without tests, refactoring or adding new event types risks breaking the dispatch chain. Snapshot or state-transition tests would document expected behavior and prevent regressions when contributors modify event handling logic.

  • [ ] Create src/event_dispatcher_tests.rs or add #[cfg(test)] to src/event_dispatcher.rs
  • [ ] Add tests for key event dispatching (navigation, filter editing, mode switching)
  • [ ] Add tests for state consistency after event sequences (e.g., open editor → type filter → apply)
  • [ ] Add tests verifying context mutations via event_dispatcher match expected side effects
  • [ ] Document event flow in comments to guide contributors on adding new event types

🌿Good first issues

  • Add unit tests for src/completion.rs to verify object-index and array-index path suggestions work correctly for nested structures with special characters
  • Document the configuration schema (default.toml) with inline comments and examples for each keybind, debounce timing, and color setting
  • Add streaming benchmark test in tests/ to measure performance on large JSON Lines files (10k+ objects) and optimize StreamDeserializer usage in src/json.rs

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 871a828 — Merge pull request #110 from ynqa/v0.7.1/dev (ynqa)
  • 647a748 — Merge pull request #112 from ynqa/tab (ynqa)
  • 3899506 — cargo-clippy (ynqa)
  • 84535aa — fix: do not replace text when suggestions are empty (ynqa)
  • ecb4685 — chore: import ordering (ynqa)
  • dadc9c3 — Merge pull request #111 from ynqa/tidy-up (ynqa)
  • 471b521 — tests: await after abort (ynqa)
  • 3fb8f89 — chore: bump up toml crate version (ynqa)
  • 5022efb — docs: guide (ynqa)
  • 6121fc7 — chore: tidy up to convert pane into somethings (ynqa)

🔒Security observations

The jnv codebase demonstrates a reasonably secure posture for a CLI application. The project uses Rust, which provides memory safety guarantees, and leverages jaq for safe JSON filtering rather than shell-executing external tools. No hardcoded credentials were identified. Primary concerns are: (1) Docker base image pinning and version management, (2) Input validation for large/malicious JSON files causing DoS, (3) Configuration file permission validation, and (4) Regular dependency auditing via cargo audit. The application handles interactive terminal UI and clipboard operations safely. Recommend implementing resource limits for JSON processing and establishing a dependency security scanning pipeline in CI/CD.

  • Medium · Outdated Rust Base Image — Dockerfile (line 1 and 8). The Dockerfile uses Rust 1.86.0-slim-bookworm as the builder base image. While this is a specific version, there is no explicit pinning of the final debian:bookworm-slim image tag, which could lead to pulling a different version on rebuilds. Additionally, Rust 1.86.0 may have known vulnerabilities that are patched in newer versions. Fix: Pin the Debian image to a specific SHA256 digest: 'debian:bookworm-slim@sha256:...' and regularly update to the latest patched Rust version. Consider using a SBOM tool to track dependencies.
  • Medium · Dependency Vulnerability: anyhow 1.0.102 — Cargo.toml (anyhow = "1.0.102"). The anyhow error handling library version 1.0.102 is used without upper bounds. While anyhow is generally safe, unconstrained dependency versions can introduce breaking changes or security issues in transitive dependencies. Fix: Consider using a caret constraint: anyhow = "^1.0.102" or review the RUSTSEC advisory database regularly using cargo audit.
  • Low · Clipboard Access Library (arboard) — Cargo.toml (arboard dependency with wayland-data-control feature). The arboard crate (3.6.1) is used with wayland-data-control features enabled, providing clipboard access functionality. While necessary for the application's copy/paste features, this increases the attack surface by allowing clipboard data manipulation. Fix: Ensure clipboard operations are validated and sanitized. Consider implementing clipboard access guards and limiting clipboard operations to user-initiated actions only. Monitor arboard security updates closely.
  • Low · Insufficient Input Validation in JSON Processing — src/json.rs, src/json_viewer.rs, src/query_editor.rs. The application processes arbitrary JSON input via jq filters. While jaq is used (safer than external jq), there is potential risk of DoS attacks through deeply nested JSON or extremely large files causing excessive memory consumption or processing time. Fix: Implement JSON size limits, nesting depth restrictions, and timeout mechanisms for filter execution. Add resource consumption limits (max file size, max execution time) in configuration.
  • Low · Unvalidated Configuration File Loading — src/config.rs, Cargo.toml (dirs = "6.0.0"). The application loads TOML configuration from default.toml and user config directory (via dirs crate). If user configuration paths are predictable and world-writable, malicious actors could inject malicious configuration. Fix: Validate configuration file permissions (ensure user-only read/write via 0600). Implement configuration schema validation. Log configuration loading and changes. Consider signing configuration files.
  • Low · Stdout Redirection Complexity — src/stdout_redirect.rs. The src/stdout_redirect.rs module handles stdout redirection, which could potentially be manipulated if input sources are compromised or if privilege escalation occurs. Fix: Ensure stdout redirection cannot be exploited for privilege escalation. Validate all redirected output. Consider running with minimal required privileges.
  • Info · No SPDX License Identifier in Dockerfile — Dockerfile. While the Cargo.toml correctly specifies MIT license, the Dockerfile lacks any license comments or headers. Fix: Add license header comments to the Dockerfile for clarity: '# SPDX-License-Identifier: MIT'

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · ynqa/jnv — RepoPilot