Command-line interface¶
Installing jsonl adds a jsonl command (equivalently python -m jsonl) that brings the
library's streaming, compression, URL, and archive features to the shell — no Python code needed.
| Argument | Description |
|---|---|
INFILE |
Input file, archive (ZIP or TAR), or URL. Reads from stdin when omitted or -. |
OUTFILE |
Output file. Writes to stdout when omitted. |
Input is processed as a stream, so memory stays constant regardless of size. Compression is
handled automatically: the output codec is chosen from the file extension (.gz, .bz2, .xz,
.zst Python ≥ 3.14), and input compression is detected from the extension or the first bytes
(magic numbers) — including stdin and URLs.
Options¶
| Option | Description |
|---|---|
--compact |
Write records in the most compact form (no spaces). |
--sort-keys |
Sort object keys alphabetically. |
--ascii |
Escape non-ASCII characters as \uXXXX. Output is raw UTF-8 by default. |
--member PATTERN |
Pick local or remote archive members by shell-style pattern. Without it, archives auto-select recognized .jsonl/.ndjson members and their supported compressed variants. |
--broken |
Skip invalid records instead of aborting (see Error handling). |
--split N |
Write at most N records per output file. |
--version |
Show the version and exit. |
-h, --help |
Show the help message and exit. |
Examples¶
# Validate and pretty-pass a file (aborts on the first invalid record)
jsonl data.jsonl
# Convert between files; compression follows the extension (gzip in, zstd out)
jsonl data.jsonl.gz data.jsonl.zst
# Pipe through a shell pipeline
cat data.jsonl | jsonl --compact > compact.jsonl
# Load directly from a URL (auto-decompressed)
jsonl https://example.com/data.jsonl.gz > data.jsonl
# Read an archive: recognized JSONL/NDJSON members are auto-discovered and streamed
jsonl dataset.zip > merged.jsonl
# Remote archives are detected from their content, even without a file extension
jsonl 'https://example.com/download?id=123' > merged.jsonl
# Select specific members from an archive
jsonl --member '2026/*.jsonl' dataset.tar.gz > year.jsonl
# Tolerate broken input: skip invalid records and report them to stderr
jsonl --broken messy.jsonl clean.jsonl
# Split into 50,000-record gzip files
jsonl --split 50000 input.jsonl users.jsonl.gz
# Reformat: sort keys and escape non-ASCII to pure ASCII
jsonl --sort-keys --ascii data.jsonl > normalized.jsonl
Splitting¶
--split N streams the input into sequential files of at most N records. Indexing starts at 00000 and uses five
zero-padded digits. The index is inserted before a recognized JSONL or NDJSON suffix, preserving compression:
users.jsonl.gz creates users-00000.jsonl.gz, users-00001.jsonl.gz, and so on.
Splitting uses the existing incremental multipath writer with one open destination at a time. It does not create a manifest and does not publish all shards atomically: if input processing fails, files already written remain available.
No --indent
Spreading a value across multiple lines would break the JSON Lines format (one value per
line), so --indent is intentionally unsupported.
Error handling¶
By default the first invalid record aborts processing. With --broken, invalid records are
skipped and reported to stderr (with the input line number when available) while the rest continue.
--broken covers only recoverable JSON parsing errors; I/O, filesystem, archive, and compression
errors always abort.
Atomic output files
When writing to a file without --split, output goes to a temporary file that atomically replaces the
destination only after the whole input succeeds — a failed run never leaves a partial file,
and the existing destination is untouched. Input and output may not be the same file. When
writing to stdout, valid records may already be emitted before an error, since stdout
cannot be rolled back.
Exit codes¶
| Code | Meaning |
|---|---|
0 |
Success — all records valid. |
1 |
One or more invalid JSON records. |
2 |
Invalid command-line usage or configuration. |
3 |
Unexpected I/O, filesystem, archive, compression, or runtime error. |
Non-UTF-8 terminals
Output is UTF-8 by default (like jq) and written as UTF-8 regardless of locale, so redirects
and pipes always get valid bytes. A legacy non-UTF-8 console may display non-ASCII as mojibake
(a rendering issue, not corruption) — use --ascii, or switch the console to UTF-8
(chcp 65001 on Windows).