Docs
The reference library is written in TypeScript, has no runtime dependencies and runs in Node.js 20+, Deno, Bun and browsers.
Status: LWON is in 1.0 beta. The library is on npm as
@lwon/core; the format may still change before 1.0. Source on GitHub. You can also try it in the playground.
Install
npm install @lwon/core
Encode and decode
import { encode, decode } from '@lwon/core';
const text = encode([
{ id: 1, name: 'Ada', role: 'admin' },
{ id: 2, name: 'Linus', role: 'dev' },
]);
// id name role
// [
// [1 Ada admin]
// [2 Linus dev]
// ]
decode(text); // the same array back
encode accepts anything JSON.stringify accepts, with the same rules: Date
becomes a string, undefined object keys are dropped, and toJSON is honoured.
decode returns plain JSON values.
Object key order is not significant in JSON, and LWON may change it: keys come back in header order. Everything else round-trips exactly.
Options
encode(value, { bareStrings: false });
| Option | Default | Effect |
|---|---|---|
bareStrings | true | Write strings such as Alice or user@example.com without quotes. Set false to quote every string. |
keyedBelow | 0.5 | Keys found in fewer than this share of the rows are written by name in the row’s * slot instead of by position. Set 0 to keep every key positional. |
Sparse keys
When most objects lack a key, writing it by position fills rows with ~, and
language models spend extra reasoning to line the values up. By default such
keys move to a * slot at the end of the header, and each row names them:
id level userId *
[
[1 info 7]
[2 warn ~ {"retry":2,"region":null}]
]
In our evals this brought the extra reasoning on sparse data close to JSON’s, at the cost of a few more tokens. See Benchmarks.
Errors
decode throws an LwonError with the position of the problem:
import { decode, LwonError } from '@lwon/core';
try {
decode('id name\n[[1 Ada extra]]');
} catch (e) {
if (e instanceof LwonError) {
e.message; // "Record has more values than the 2 fields in its header (line 2, column 9)"
e.line; // 2
e.column; // 9
}
}
Prompts
PRIMER is a short explanation of the format for language models. Send it once
alongside LWON data. See For AI for when this pays off.
import { encode, PRIMER } from '@lwon/core';
const prompt = `${PRIMER}\n\n${encode(toolResult)}`;
Command line
npx @lwon/core encode data.json > data.lwon # JSON to LWON
npx @lwon/core decode data.lwon --pretty # LWON to JSON
npx @lwon/core stats data.json # bytes for indented JSON, minified JSON and LWON
npx @lwon/core primer # print the prompt primer
Every command reads standard input when no file is given. Installed globally
(npm install -g @lwon/core), the command is simply lwon.
MCP servers
@lwon/mcp-proxy converts the
JSON tool results of any stdio MCP server to LWON. Put it in front of the
server’s command:
npx -y @lwon/mcp-proxy -- npx -y @modelcontextprotocol/server-github
Setup for Claude Code and Claude Desktop is on the For AI page.
Other languages
The conformance suite is plain JSON, so any implementation can run it:
| File | What an implementation must do |
|---|---|
roundtrip.json | decode(encode(json)) equals json |
decode.json | decode(lwon) equals json |
invalid.json | decode(lwon) fails |
encode.json | The reference encoder’s exact output. Optional for other encoders. |