@creationix/jot
v0.1.1
Published
LLM and human friendly JSON alternative
Downloads
302
Readme
Jot Format
Jot is a compact, human-readable JSON variant that uses fewer tokens for LLM applications.
JSON:
{"context":{"task":"Our favorite hikes together","location":"Boulder"},"friends":["ana","luis","sam"],"hikes":[{"id":1,"name":"Blue Lake Trail","km":7.5},{"id":2,"name":"Ridge Overlook","km":9.2}]}Jot:
{context:{task:Our favorite hikes together,location:Boulder},friends:[ana,luis,sam],hikes:{{:id,name,km;1,Blue Lake Trail,7.5;2,Ridge Overlook,9.2}}}Same data, 26% fewer tokens, still readable.
Why Jot?
- Save on LLM costs — Fewer tokens = lower API bills
- Fit more in context — Get more data into your prompts
- Human readable — Unlike binary formats, you can read and write it directly
- JSON compatible — Parses to the same JavaScript objects
Token Savings
Across 18 sample files, Jot averages 13% token savings.
| Sample | JSON | Jot | Savings | |--------|------|-----|---------| | users-50 | 1327 | 837 | 37% | | products | 772 | 613 | 21% | | large | 240 | 221 | 8% | | small | 37 | 36 | 3% | | irregular | 49 | 49 | 0% |
Installation
npm / pnpm / yarn
npm i --save @creationix/jotCommonJS
const { parse, stringify } = require("@creationix/jot");ES Modules
import { parse, stringify } from "@creationix/jot";Browser
Copy dist/jot.js to your project and import as a native ES module:
<script type="module">
import { parse, stringify } from "./jot.js";
</script>TypeScript
TypeScript definitions are included. You can also import src/jot.ts directly into your project.
Usage
import { parse, stringify } from "@creationix/jot";
// Parse Jot to JavaScript
const data = parse("{name:Alice,scores:[98,87,92]}");
// { name: "Alice", scores: [98, 87, 92] }
// Stringify JavaScript to Jot
const jot = stringify({ name: "Bob", active: true });
// {name:Bob,active:true}
// Pretty print with options
const pretty = stringify(data, { pretty: true, indent: " " });Syntax
Jot is JSON with three optimizations:
- Unquoted strings — Strings are only quoted if necessary
- Key folding — Single-key nested objects collapse:
{a:{b:1}}→{a.b:1} - Tables — Arrays of objects with the same schema use
{{:cols;row;row}}syntax
Here's a complete example showing all three:
{
context: {
task: Our favorite hikes together,
location: Boulder,
season: spring_2025
},
friends: [ ana, luis, sam ],
hikes: {{
:id, name, distanceKm, elevationGain, companion, wasSunny
1, Blue Lake Trail, 7.5, 320, ana, true
2, Ridge Overlook, 9.2, 540, luis, false
3, Wildflower Loop, 5.1, 180, sam, true
}}
}Unquoted Strings
Quote a string only when:
- It's a reserved value (
true,false,null) or a number (42,3.14,-0.5,1e10) - It contains special characters:
: ; , { } [ ] "or control characters - It's empty or has leading/trailing whitespace
- It's a key containing
.(to distinguish from folded keys)
{"name":"Alice","city":"New York","count":"42"}{name:Alice,city:New York,count:"42"}Key Folding
When a nested object has exactly one key, fold it:
{"server":{"host":"localhost"}}{server.host:localhost}If a key itself contains dots, quote it to avoid confusion:
{"data.point":{"x":10,"y":20}}{"data.point":{x:10,y:20}}Tables
Arrays of objects with repeating schemas become tables. Start with : followed by column names:
[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]{{:id,name;1,Alice;2,Bob}}To change schema mid-table, add another :schema; row:
[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"},{"x":10,"y":20},{"x":30,"y":40}]{{:id,name;1,Alice;2,Bob;:x,y;10,20;30,40}}Don't use tables when there's no schema reuse — regular arrays are more compact.
