Skip to content

Command Line Tool

Daniël Smith edited this page Oct 11, 2026 · 4 revisions

Command-Line Tool

The npm package includes jazmin, a command-line tool for looking into, querying and converting files without writing code. It needs Node.js 22 or later.

npx @smithsoft-studios/jazmin --help     # without installing
npm install -g @smithsoft-studios/jazmin # or install it: then just `jazmin --help`
Command What it does
jazmin inspect <file> What the file holds, as JSON: format, encryption, tables, rows, chunks, sort order, columns, indexes, access and embedded files
jazmin query <file> --filter '<json>' --select a,b --offset n --limit n --format jsonl|json|csv The matching rows, as JSON lines (the default), a JSON array or CSV
jazmin query <file> --shape '<name>' | --shape-file <shape.json> --format json|xml The output of an export shape saved in the file (by name) or in a JSON file, as JSON (the default) or XML (1.5.0); inspect lists a file's saved shapes
jazmin explain <file> --filter '<json>' --analyze How a query runs and, with --analyze, what it read
jazmin advise <file> --column <name> Layout advice for lookups of a column
jazmin convert <input> <output> JSON, JSON Lines, CSV or XML to .jzm (--sorted-by a,b), or .jzm to JSON, CSV or XML (--filter)
jazmin keygen [--access] A new key or, with --access, an access key issued from the owner key
jazmin script <file.jzm> [<file.js>] [--name <name>] The file as a script (default: <file.jzm>.js beside it), which a page opened from disk opens with JazminBrowser.openScript() (Viewer and Browser). Needs no key: the file inside stays encrypted. New in 1.5.0

Every command takes --help, and --table <name> picks a table in a file with several.

Keys stay out of your shell history

Keys come from the environment (JAZMIN_KEY, JAZMIN_PASSWORD, JAZMIN_UNLOCK_TOKEN) or from files (--key-file, --password-file, --unlock-token-file). The tool never prints a key, except keygen, whose output belongs in a file or a secret manager:

jazmin keygen > owner.key                              # keep this file safe; better: put it in a secret manager
export JAZMIN_KEY="$(cat owner.key)"
jazmin convert transactions.csv transactions.jzm       # encrypted, because JAZMIN_KEY is set
jazmin query transactions.jzm --limit 1 --key-file owner.key

Exit codes: 0 on success, 1 when the file or key is the problem (the message says why), 2 when the command line is wrong. That makes the tool easy to use in scripts and CI.

A session

The output below is from version 1.2.0, on a CSV of 50,000 transactions for 250 accounts, already in account order.

Convert. --sorted-by declares the order the rows are already in (it doesn't sort them); a row out of order stops the conversion with Row 250 is out of order for sortedBy [account].

jazmin convert transactions.csv transactions.jzm --sorted-by account

Inspect (abridged):

$ jazmin inspect transactions.jzm
{
  "file": "transactions.jzm",
  "bytes": 41634,
  "fileId": "…",
  "version": "1.0",
  "encrypted": false,
  "rows": 50000,
  "chunks": 13,
  "sortedBy": [ "account" ],
  "columns": [
    { "name": "account", "type": "string", "nullable": false },
    { "name": "at", "type": "string", "nullable": false },
    { "name": "amount", "type": "float", "nullable": false },
    { "name": "memo", "type": "string", "nullable": false }
  ],
  "indexes": [],
  "access": null,
  "files": 0,
  "metadata": {}
}

The CSV's dates were inferred as text; to store real dates, convert in code with declared columns (see Converting JSON, CSV and XML). Without a key, inspect on an encrypted file shows only its format and flags.

Query:

$ jazmin query transactions.jzm --filter '{"account":"ACC-042"}' --select at,amount --limit 3
{"at":"2026-01-01T10:00:00Z","amount":100}
{"at":"2026-01-02T10:00:00Z","amount":100.25}
{"at":"2026-01-03T10:00:00Z","amount":100.5}

$ jazmin query transactions.jzm --filter '{"memo":"refund"}' --limit 3 --format csv
account,at,amount,memo
ACC-000,2026-01-01T10:00:00Z,0,refund
ACC-002,2026-02-17T10:00:00Z,125,refund
ACC-005,2026-01-01T10:00:00Z,0,refund

The filter is the filter language, as JSON. On Windows PowerShell, quote it with single quotes as shown; in cmd.exe, use double quotes and escape the inner ones ("{\"account\":\"ACC-042\"}").

Explain:

$ jazmin explain transactions.jzm --filter '{"account":"ACC-042"}' --analyze
{
  "strategy": "scan",
  "chunks": 13,
  "chunksSkipped": 12,
  "rows": 200,
  "bytesRead": 3444,
  "chunksRead": 1,
  "indexPagesRead": 0,
  "columnsDecoded": 4,
  "ms": …
}

The file is sorted by account, so chunk statistics skip 12 of 13 chunks and one account's 200 rows cost 3 KB.

Advise:

$ jazmin advise transactions.jzm --column memo
50,000 rows in 13 chunks (about 3,846 rows, 3 KB each), sorted by account
memo: one value's rows lie in about 13 chunk(s), about 40 KB to read
- The rows of one 'memo' value lie in about 13.0 of 13 chunks: a lookup reads about 40 KB. Writing the file with sortedBy: ["memo","account"] would put them in a few chunks.

advise reads only chunk directories and statistics, not rows, so it is fast on any size of file. --json prints the advice as JSON. In access-controlled files it also lists each partition's chunks and suggests compact({ regroup: true }) when appends have spread a partition out. See Tuning Speed and Memory.

Convert back out, streamed with bounded memory:

$ jazmin convert transactions.jzm acc42.csv --filter '{"account":"ACC-042"}'
$ head -3 acc42.csv
account,at,amount,memo
ACC-042,2026-01-01T10:00:00Z,100,card
ACC-042,2026-01-02T10:00:00Z,100.25,card

Access keys from the command line

export JAZMIN_KEY="$(cat owner.key)"    # the owner key of a shared file
jazmin keygen --access > ann.key        # a new access key issued from it

The new key opens nothing until it is granted rows and columns: grantAccess() in code, or update({ grant }). See Access Control.

Clone this wiki locally