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 });
OptionDefaultEffect
bareStringstrueWrite strings such as Alice or user@example.com without quotes. Set false to quote every string.
keyedBelow0.5Keys 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:

FileWhat an implementation must do
roundtrip.jsondecode(encode(json)) equals json
decode.jsondecode(lwon) equals json
invalid.jsondecode(lwon) fails
encode.jsonThe reference encoder’s exact output. Optional for other encoders.