RepoPilotOpen in app →

PaulJuliusMartinez/jless

jless is a command-line JSON viewer designed for reading, exploring, and searching through JSON data.

Mixed

Single-maintainer risk — review before adopting

weakest axis
Use as dependencyMixed

top contributor handles 93% of recent commits; 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 3d ago
  • 7 active contributors
  • MIT licensed
Show all 6 evidence items →
  • CI configured
  • Single-maintainer risk — top contributor 93% of recent commits
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: diversify commit ownership (top <90%)

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/pauljuliusmartinez/jless?axis=fork)](https://repopilot.app/r/pauljuliusmartinez/jless)

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/pauljuliusmartinez/jless on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: PaulJuliusMartinez/jless

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/PaulJuliusMartinez/jless 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 — Single-maintainer risk — review before adopting

  • Last commit 3d ago
  • 7 active contributors
  • MIT licensed
  • CI configured
  • ⚠ Single-maintainer risk — top contributor 93% of 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 PaulJuliusMartinez/jless repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/PaulJuliusMartinez/jless.

What it runs against: a local clone of PaulJuliusMartinez/jless — 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 PaulJuliusMartinez/jless | 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 ≤ 33 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>PaulJuliusMartinez/jless</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of PaulJuliusMartinez/jless. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/PaulJuliusMartinez/jless.git
#   cd jless
#
# 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 PaulJuliusMartinez/jless and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "PaulJuliusMartinez/jless(\\.git)?\\b" \\
  && ok "origin remote is PaulJuliusMartinez/jless" \\
  || miss "origin remote is not PaulJuliusMartinez/jless (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/app.rs" \\
  && ok "src/app.rs" \\
  || miss "missing critical file: src/app.rs"
test -f "src/jsonparser.rs" \\
  && ok "src/jsonparser.rs" \\
  || miss "missing critical file: src/jsonparser.rs"
test -f "src/flatjson.rs" \\
  && ok "src/flatjson.rs" \\
  || miss "missing critical file: src/flatjson.rs"
test -f "src/viewer.rs" \\
  && ok "src/viewer.rs" \\
  || miss "missing critical file: src/viewer.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 33 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~3d)"
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/PaulJuliusMartinez/jless"
  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

jless is a command-line JSON viewer written in Rust that renders JSON with syntax highlighting, expandable/collapsible objects and arrays, and vim-inspired navigation commands. It replaces tedious piping through less, jq, and cat with a single interactive binary that lets you explore JSON structure at multiple levels of detail and search with regex. Single-binary architecture: src/main.rs orchestrates the CLI, src/app.rs contains the core application state machine, src/flatjson.rs handles JSON flattening for the display layer, src/viewer.rs manages interactive navigation, and src/search.rs implements regex search. Parsing delegates to src/jsonparser.rs and src/yamlparser.rs. Rendering flows through src/screenwriter.rs → src/lineprinter.rs.

👥Who it's for

DevOps engineers, backend developers, and data analysts who regularly inspect large JSON files in the terminal—they need to quickly navigate deeply nested structures and search for specific fields without memorizing jq syntax or writing throwaway scripts.

🌱Maturity & risk

Production-ready. The project is at v0.9.0 with a complete CI/CD pipeline (GitHub Actions in .github/workflows/), packages available across macOS, Linux, Arch, FreeBSD, and others. The codebase is 387KB of Rust with careful attention to testing and release procedures (RELEASE_CHECKLIST.md exists), indicating sustained maintenance and user trust.

Low risk. The dependency surface is modest (logos, termion, regex, clap, yaml-rust, clipboard, signal-hook) with no transitive explosion. The project is single-maintainer (PaulJuliusMartinez) but has explicit Windows support planned and formal release documentation, suggesting longevity intent. No obvious abandonment signals—however, contributor onboarding resources are sparse.

Active areas of work

Based on the Cargo.toml (v0.9.0) and structured release checklist, the project is in maintenance mode with incremental feature development. The repo structure suggests active work on search capabilities (SEARCH.md documentation exists) and terminal rendering optimization (src/render-notes.md). Windows support is an explicit TODO.

🚀Get running

git clone https://github.com/PaulJuliusMartinez/jless.git
cd jless
cargo build --release
./target/release/jless examples/escaped_strings_for_yanking.json

Daily commands:

cargo run -- <json-file>
# or for interactive dev with reload:
cargo watch -x 'run -- examples/escaped_strings_for_yanking.json'

🗺️Map of the codebase

  • src/main.rs — Entry point that initializes the application, parses command-line arguments, and orchestrates the main event loop.
  • src/app.rs — Core application state machine managing the viewer's interaction flow, user input handling, and rendering coordination.
  • src/jsonparser.rs — Parses JSON input into a hierarchical structure; critical for data representation and tree navigation.
  • src/flatjson.rs — Flattens JSON tree structures for efficient line-by-line rendering and navigation without full materialization.
  • src/viewer.rs — Manages viewport logic, line rendering, cursor positioning, and expansion/collapse state for the display.
  • src/search.rs — Implements regex-based search across JSON data, yielding match results for interactive navigation.
  • src/screenwriter.rs — Terminal rendering layer that applies syntax highlighting and writes styled output to the screen.

🛠️How to make changes

Add a new keyboard command/navigation feature

  1. Define the new key binding in the input handling match statement within app.rs's event loop (src/app.rs)
  2. Implement the corresponding state mutation or viewer method (e.g., scroll, expand, collapse, jump) (src/app.rs)
  3. Document the new command in the help text file (src/jless.help)

Add support for a new data format (e.g., JSON5, MessagePack)

  1. Create a new parser module (e.g., src/json5parser.rs) following the pattern of jsonparser.rs and yamlparser.rs (src/jsonparser.rs)
  2. Add a format detection check in main.rs or input.rs based on file extension or content (src/input.rs)
  3. Call the new parser from app initialization and convert result to the shared Value type (src/types.rs)

Enhance syntax highlighting with new color schemes or rules

  1. Add new token types or color mappings in the highlighting module (src/highlighting.rs)
  2. Update the lineprinter to apply new highlighting rules when generating formatted output (src/lineprinter.rs)
  3. Test rendering via screenwriter.rs to ensure terminal color output is correct (src/screenwriter.rs)

Improve search functionality (e.g., case-insensitive, fuzzy matching)

  1. Extend the regex compilation and search logic in search.rs with new matching strategies (src/search.rs)
  2. Add CLI flags for search options in options.rs (e.g., --case-insensitive) (src/options.rs)
  3. Integrate the new search mode into app.rs's search trigger and result navigation (src/app.rs)

🔧Why these technologies

  • Rust — Type safety, memory efficiency, and single-binary deployment critical for a CLI tool; zero-cost abstractions enable responsive UI.
  • logos lexer framework — Efficient tokenization of large JSON inputs; lazy evaluation prevents memory overhead on large files.
  • termion — Cross-platform (macOS/Linux) terminal control without external dependencies; enables raw mode and color output.
  • regex crate — Full regex support for search queries; compiled patterns enable fast repeated matching across JSON structures.
  • rustyline — Interactive command-line editing for search input; provides history and readline-like UX conventions.
  • signal-hook — Graceful handling of SIGWINCH (window resize) and SIGINT (Ctrl+C) without blocking event loop.
  • clap derive — Zero-cost CLI argument parsing; declarative approach reduces boilerplate and enables auto-generated help.

⚖️Trade-offs already made

  • Flatten JSON tree on-demand rather than materializing all lines upfront

    • Why: Enables efficient navigation of multi-gigabyte JSON files without loading entire structure into memory.
    • Consequence: Line number calculations are O(n) worst-case; caching would require tracking invalidation on expand/collapse.
  • Single-threaded synchronous event loop with blocking terminal I/O

    • Why: Simplifies state management and eliminates race conditions; sufficient for interactive CLI workload.
    • Consequence: Cannot parallelize large JSON parsing; extremely large files may feel sluggish during initial load.
  • Store full JSON Value tree in memory; no streaming parser

    • Why: Enables arbitrary navigation (jump, search, expand/collapse) without re-parsing; required for interactive viewer.
    • Consequence: Out-of-memory on JSON files larger than available RAM; no progressive rendering for slow networks.
  • Regex-based search over tree structure queries (no JSONPath, jq syntax)

    • Why: Simpler mental model; integrates with standard Unix grep/sed workflows; regexes handle most use cases.
    • Consequence: Complex structural queries require custom regex; less expressive than purpose-built query languages.
  • Custom JSON parser instead of serde_json

    • Why: Fine-grained control over error reporting, formatting output, and whitespace preservation in yank feature.
    • Consequence: Higher maintenance burden; must handle edge cases (control characters, very large numbers, Unicode) manually.

🚫Non-goals (don't propose these)

  • Windows support (currently macOS/Linux only, per README)
  • Real-time data streaming or progressive loading
  • JSON modification/editing (viewer-only, not an editor)
  • Batch processing or piped command chains (single-file focus)
  • Extensive formatting options or custom output templates
  • Network requests or remote JSON sources

🪤Traps & gotchas

1. Terminal state on panic: signal-hook is used to restore terminal on SIGWINCH; ensure signal handlers are tested (not visible in file list). 2. Clipboard optional complexity: clipboard dependency requires X11 libs on Linux (documented in README but easy to miss during build). 3. YAML fallback: yamlparser.rs is a fallback parser—YAML features may silently diverge from JSON behavior. 4. Unicode width handling: unicode-width and unicode-segmentation are critical for correct cursor positioning in non-ASCII JSON; bugs here cause UI misalignment. 5. Logos lexer limitations: src/jsontokenizer.rs uses logos macros; mistakes in regex patterns are compile-time errors only visible during cargo build.

🏗️Architecture

💡Concepts to learn

  • Lexical analysis with logos — src/jsontokenizer.rs uses the logos crate to generate a fast, declarative lexer for JSON; understanding how regex-based token patterns compose is essential for modifying JSON parsing
  • Flat display model (view-model separation) — jless converts nested JSON into a flat sequence of lines (flatjson.rs), decoupling the data structure from the viewport rendering; this pattern enables efficient scrolling and line-based selection without traversing the AST repeatedly
  • Terminal control abstraction (termion) — src/screenwriter.rs wraps termion to abstract raw ANSI sequences; understanding cursor positioning, color codes, and screen state is critical for rendering bugs and feature additions like mouse support
  • Signal handling for terminal resize (SIGWINCH) — signal-hook manages graceful reflow on terminal resize; mishandling SIGWINCH can corrupt the viewport or crash the app, making this non-obvious but critical for reliability
  • Regular expression anchoring in search — src/search.rs implements regex-based search; understanding how regex patterns are anchored to keys vs. values and how lookahead/lookbehind affect performance is key for search feature PRs
  • Expanded/collapsed state machine — src/viewer.rs tracks which objects/arrays are expanded; maintaining consistency between user input, state transitions, and the flattened display requires careful state management to avoid UI glitches
  • Unicode grapheme and width handling — unicode-segmentation and unicode-width ensure cursor positioning accounts for multi-byte characters and zero-width glyphs; ignoring this breaks rendering for non-ASCII JSON keys and string values
  • stedolan/jq — The canonical JSON query language; jless is designed as a UI replacement for jq's query-less use case (just viewing/exploring)
  • BurntSushi/xsv — Similar single-binary CLI tool for CSV exploration with indexing and search; shares the philosophy of replacing ad-hoc tool chains
  • ogham/exa — Modern Rust CLI replacing ls with color/icons; demonstrates the pattern of reimplementing classic Unix tools with UX improvements
  • sharkdp/bat — Rust replacement for cat with syntax highlighting; jless follows the same philosophy for JSON specifically
  • jqlang/jq — Active jq fork; understanding jq's AST and query semantics is valuable for anyone contributing complex search/filter features to jless

🪄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 comprehensive unit tests for src/jsonstringunescaper.rs

The jsonstringunescaper module handles critical string unescaping logic (referenced in examples/escaped_strings_for_yanking.json), but there are no visible test files in src/ for this module. This is a high-risk area for bugs since string escaping/unescaping edge cases are notoriously tricky. Adding unit tests would catch regressions in Unicode, control characters, and escape sequence handling.

  • [ ] Create tests module in src/jsonstringunescaper.rs with test cases for common escape sequences (\n, \t, \u0000, etc.)
  • [ ] Add edge case tests for nested quotes, backslashes, and invalid UTF-8 sequences
  • [ ] Test the example from examples/escaped_strings_for_yanking.json to ensure round-trip correctness
  • [ ] Run cargo test to verify coverage and document test results

Add integration tests for src/search.rs with real JSON inputs

The search functionality is a core feature (documented in SEARCH.md) but lacks visible integration tests. Given the complexity of regex-based search with JSON structure awareness, integration tests using actual JSON files would prevent regressions and make the search behavior more maintainable for contributors.

  • [ ] Create tests/search_integration_tests.rs with sample JSON fixtures
  • [ ] Add test cases for basic regex search, case sensitivity, nested key matching, and value search
  • [ ] Test edge cases like searching in escaped strings, numbers, and boolean values
  • [ ] Verify search results match expected line numbers and node paths in the JSON structure

Document the YAML support feature with examples in README.md

The codebase includes src/yamlparser.rs and a 'sexp' feature flag in Cargo.toml, suggesting YAML and possibly S-expression support exists, but the README.md is incomplete (cuts off mid-sentence) and contains no mention of these formats. This is confusing for users and contributors. Completing the README with format support documentation and updating examples would clarify capabilities.

  • [ ] Complete the truncated README.md sentence and add a 'Supported Formats' section
  • [ ] Document the YAML parsing feature with usage example: jless --yaml file.yaml
  • [ ] Clarify what the 'sexp' feature flag enables and provide an example if applicable
  • [ ] Add format auto-detection behavior to the documentation (if implemented)
  • [ ] Consider adding yaml and sexp examples to the examples/ directory

🌿Good first issues

  • Add unit tests for jsonstringunescaper.rs: The file exists but has no corresponding test file visible; add escaped string parsing tests covering \uXXXX sequences, \t\n\r, and edge cases like unmatched escapes.
  • Document viewer keybindings in code: src/jless.help exists but isn't referenced in src/viewer.rs; add inline comments mapping keycodes (termion events) to navigation actions, then sync with help text.
  • Expand flatjson.rs test coverage: This is the display rendering core but likely has few edge case tests; add tests for deeply nested structures, arrays of primitives, and null values to prevent viewport rendering bugs.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • e6cdef7 — Add [sexp] feature and :writesexp function to write input to a file as a sexp. (PaulJuliusMartinez)
  • bd58080 — Add :write <file> (and :write!) commands for writing input to a file. (PaulJuliusMartinez)
  • 3d1c43f — Ctrl-z now suspends jless. (PaulJuliusMartinez)
  • b445731 — Update Arch Linux package URL in README.md (#139) (felixonmars)
  • a469b27 — Fix a few spelling mistakes. (PaulJuliusMartinez)
  • 5e0f71f — Still under development, but not very active; a little haphazard to be honest. I definitely don't stream on Twitch anymo (PaulJuliusMartinez)
  • 7142c9a — Add clarifying note to RELEASE_CHECKLIST.md because I messed up the first time. (PaulJuliusMartinez)
  • ee848bd — Move cargo install jless to the Installation table proper (#122) (GeroVanMi)
  • 21dd610 — v0.9.0 Release (PaulJuliusMartinez)
  • 5d5a597 — Add 'C' and 'E' commands to deeply collapse/expand nodes. (PaulJuliusMartinez)

🔒Security observations

The jless codebase demonstrates good security practices overall, with no critical vulnerabilities identified. However, several medium and low-risk issues exist: (1) use of deprecated lazy_static crate which is no longer maintained, (2) outdated regex crate version missing performance/security improvements, (3) direct terminal and system-level interactions that require careful signal handling, and (4) clipboard access that should be gated behind explicit user actions. The application is designed to process untrusted JSON/YAML input, which is its intended use case, but parser robustness should be audited. The Rust ecosystem and memory safety features provide strong foundational security; the primary concerns are dependency maintenance and ensuring user-facing features (like clipboard access) are properly controlled.

  • Medium · Deprecated/Unmaintained Dependency: lazy_static — Cargo.toml - dependencies. The lazy_static crate (version 1.4.0) is deprecated and no longer maintained. The Rust ecosystem has moved to using std::sync::OnceLock (stabilized in Rust 1.70) or the once_cell crate as replacements. Using unmaintained dependencies can lead to unpatched security issues. Fix: Migrate from lazy_static to std::sync::OnceLock (requires bumping MSRV to 1.70+) or use the once_cell crate as an interim solution.
  • Medium · Outdated Regex Crate — Cargo.toml - dependencies. The regex crate version 1.5 is significantly outdated (current stable is 1.10+). While regex crates rarely have critical vulnerabilities, staying on old versions means missing performance improvements and potential DoS mitigations in regex processing. Fix: Update regex to the latest stable version (1.10 or higher) to benefit from performance improvements and security patches.
  • Low · Terminal Interaction via Termion — Cargo.toml - dependencies (termion, signal-hook, libc). The application uses termion (1.5.6) for terminal control and also imports libc directly. While termion is a reputable crate, direct terminal manipulation combined with signal-hook and libc could introduce subtle race conditions or security issues if not handled carefully. Fix: Ensure proper signal handling and synchronization when using signal-hook with terminal I/O. Consider adding integration tests for signal safety.
  • Low · Clipboard Access Without Explicit User Consent UI — Cargo.toml - dependencies (clipboard). The clipboard crate (0.5) is included as a dependency, allowing the application to read/write system clipboard. While jless appears to be a viewer, clipboard functionality could potentially leak sensitive data if not carefully gated behind clear user actions. Fix: Verify that clipboard operations are explicitly requested by the user and provide clear feedback when clipboard operations occur. Document clipboard usage in the user guide.
  • Low · Missing Input Validation Audit — src/jsonparser.rs, src/yamlparser.rs, src/search.rs. The application processes untrusted JSON input from files/stdin and includes a JSON parser (jsonparser.rs), YAML parser (yamlparser.rs), and regex-based search (search.rs). While parsing untrusted data is the intended use case, potential issues could arise from malformed input handling. Fix: Conduct a security review of JSON/YAML parsing to ensure robust error handling and no unbounded recursion on deeply nested structures. Add fuzzing tests for parser robustness.
  • Low · Hardcoded Help Text — src/jless.help. The application includes a hardcoded help file (src/jless.help). While not a direct security vulnerability, maintaining help text as a separate file can reduce the attack surface if dynamic help generation is used. Fix: This is a minor concern - no immediate action needed, but consider if this helps text could be dynamically generated in future versions.

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 · PaulJuliusMartinez/jless — RepoPilot