- RX Data Store
- Skill by
- ara.so
- — Daily 2026 Skills collection.
- RX is an embedded data store for JSON-shaped data. Encode once, then query the encoded document in place — no parsing, no object graph, no GC pressure. Think of it as
- no-SQL SQLite
- unstructured data with database-style random access. Key benefits: O(1) array access, O(log n) object key lookup on encoded data Automatic deduplication of values and shared schemas Text-safe encoding (copy-paste friendly, no binary tooling needed) Minimal heap allocations (~10 vs millions for JSON parsing) ~18x compression on real deployment manifests (92 MB → 5.1 MB) Installation npm install @creationix/rx
library
npm install -g @creationix/rx
CLI (global)
npx @creationix/rx data.rx
CLI (one-off)
Core API String API (most common) import { stringify , parse } from "@creationix/rx" ; // Encode const rx = stringify ( { users : [ "alice" , "bob" ] , version : 3 } ) ; // Returns a string — store it anywhere you'd store JSON text // Decode (returns a read-only Proxy) const data = parse ( rx ) as any ; data . users [ 0 ] // "alice" data . version // 3 Object . keys ( data ) // ["users", "version"] JSON . stringify ( data ) // works — full JS interop Uint8Array API (performance-critical paths) import { encode , open } from "@creationix/rx" ; const buf = encode ( { path : "/api/users" , status : 200 } ) ; const data = open ( buf ) as any ; data . path // "/api/users" data . status // 200 Inspect API (lazy AST) import { encode , inspect } from "@creationix/rx" ; const buf = encode ( { name : "alice" , scores : [ 10 , 20 , 30 ] } ) ; const root = inspect ( buf ) ; root . tag // ":" root [ 0 ] . tag // "," (a string key) root [ 0 ] . value // "name" root . length // 4 (key, value, key, value) // Iterate children for ( const child of root ) { console . log ( child . tag , child . b64 ) ; } // Object helpers for ( const [ key , val ] of root . entries ( ) ) { / ... / } const node = root . index ( "name" ) ; // key lookup → node const elem = root . index ( 2 ) ; // array index → node // Filtered key search (O(log n + m) on indexed objects) for ( const [ key , val ] of root . filteredKeys ( "/api/" ) ) { / ... / } Escape hatch to underlying buffer import { handle } from "@creationix/rx" ; const h = handle ( data . nested ) ; // h.data: Uint8Array // h.right: byte offset Encoding Options stringify ( data , { // Add sorted indexes to containers with >= N entries (enables O(log n) lookup) // Use 0 for all containers, false to disable entirely indexes : 10 , // External refs — shared dictionary of known values for cross-document dedup refs : { R : [ "/api/users" , "/api/teams" ] } , // Streaming — receive chunks as they're produced onChunk : ( chunk : string , offset : number ) => process . stdout . write ( chunk ) , } ) ; encode ( data , { indexes : 10 , refs : { R : [ "/api/users" , "/api/teams" ] } , onChunk : ( chunk : Uint8Array , offset : number ) => { / ... / } , } ) ; If the encoder used external refs, pass the same dictionary to the decoder: const data = parse ( payload , { refs : { R : [ "/api/users" , "/api/teams" ] } } ) ; const data = open ( buf , { refs : { R : [ "/api/users" , "/api/teams" ] } } ) ; CLI rx data.rx
pretty-print as tree (default on TTY)
rx data.rx -j
convert to JSON
rx data.json -r
convert to RX
cat data.rx | rx
read from stdin (auto-detect format)
rx data.rx -s key 0 sub
select a sub-value: data["key"][0]["sub"]
rx data.rx -o out.json
write to file
rx data.rx --ast
output encoding structure as JSON
rx data.rx -w
write converted file (.json↔.rx)
Full CLI flags:
Flag
Description
Delimiter for string chains (default:
/
)
--key-complexity-threshold
or bash
Tip — paged, colorized viewing: p ( ) { rx " $1 " -t -c | less -RFX ; } Proxy Behavior The value returned by parse / open is read-only : obj . newKey = 1 ; // throws TypeError delete obj . key ; // throws TypeError "key" in obj ; // works (zero-alloc key search) obj . nested === obj . nested // true (container Proxies are memoized) Supported operations on the Proxy: Property access: data.key , data[0] Object.keys() , Object.entries() , Object.values() for...of , for...in Array.isArray() .map() , .filter() , .find() , .reduce() Spread and destructuring JSON.stringify() Common Patterns Build-step: convert JSON artifact to RX import { readFileSync , writeFileSync } from "fs" ; import { stringify } from "@creationix/rx" ; const json = JSON . parse ( readFileSync ( "manifest.json" , "utf-8" ) ) ; const rx = stringify ( json , { indexes : 10 } ) ; writeFileSync ( "manifest.rx" , rx , "utf-8" ) ; Runtime: sparse read from large RX file import { readFileSync } from "fs" ; import { parse } from "@creationix/rx" ; const manifest = parse ( readFileSync ( "manifest.rx" , "utf-8" ) ) as any ; // Only the accessed values are decoded — everything else is skipped const route = manifest . routes [ "/dashboard/projects" ] ; console . log ( route . title , route . component , route . auth ) ; Streaming encode to stdout import { stringify } from "@creationix/rx" ; stringify ( largeData , { onChunk : ( chunk , offset ) => process . stdout . write ( chunk ) , } ) ; Using external refs for cross-document deduplication import { stringify , parse } from "@creationix/rx" ; const sharedRefs = { R : [ "/api/users" , "/api/teams" , "/api/projects" ] } ; // Encode multiple documents sharing the same ref dictionary const doc1 = stringify ( data1 , { refs : sharedRefs } ) ; const doc2 = stringify ( data2 , { refs : sharedRefs } ) ; // Decode with the same dictionary const val1 = parse ( doc1 , { refs : sharedRefs } ) as any ; const val2 = parse ( doc2 , { refs : sharedRefs } ) as any ; Low-level inspect traversal (zero allocation) import { encode , inspect } from "@creationix/rx" ; const buf = encode ( routes ) ; const root = inspect ( buf ) ; // Walk object entries without creating JS objects if ( root . tag === ":" ) { for ( const [ key , val ] of root . entries ( ) ) { if ( key . value === "/dashboard" ) { console . log ( "Found:" , val . index ( "title" ) . value ) ; break ; } } } Type-safe usage pattern import { parse } from "@creationix/rx" ; interface Route { title : string ; component : string ; auth : boolean ; } interface Manifest { routes : Record < string , Route
; version : number ; } // Cast after parse — RX Proxy supports all read operations const manifest = parse ( rxString ) as unknown as Manifest ; const dashboard = manifest . routes [ "/dashboard" ] ; Format Reference RX is a text encoding — not human-readable like JSON, but safe to copy-paste. Every value is read right-to-left . The parser scans left past base64 digits to find a tag character: [body][tag][b64 varint] ◄── read this way ── JSON RX Description 42 +1k tag + (integer), b64 1k = 84, zigzag → 42 "hi" hi,2 tag , (string), length = 2 true 't tag ' (ref), built-in literal [1,2,3] +6+4+2;6 tag ; (array), b64 6 = content size {"a":1} +2a,1:a tag : (object), interleaved keys/values Tags: + integer · * decimal · , string · ' ref/literal · : object · ; array · ^ pointer · . chain ·
index When to Use RX vs Alternatives Scenario Use Large artifact, sparse reads RX Build manifests, route tables RX Small config files JSON Human-authored config JSON/YAML Write-heavy / mutable data Real database Fixed schema, minimize wire size Protobuf Relational/tabular data SQLite Minimizing compressed transfer gzip/zstd + JSON Troubleshooting TypeError: Cannot set property on decoded value The Proxy returned by parse / open is read-only by design. To mutate, spread into a plain object first: const mutable = { ... parse ( rx ) } ; mutable . newKey = "value" ; // works Decoded value looks correct but instanceof Array fails Use Array.isArray(val) instead — this is correctly intercepted by the Proxy. External refs mismatch / wrong values decoded Ensure the exact same refs dictionary (same keys, same arrays, same order) is passed to both stringify / encode and parse / open . CLI not found after global install npm install -g @creationix/rx
If still not found, check your npm global bin path:
npm bin -g Inspecting encoded bytes rx data.rx --ast
shows encoding structure with tags and offsets
Or use the live viewer at rx.run — paste RX or JSON directly. Performance: lookups slower than expected Ensure indexes threshold is set appropriately when encoding. For large objects (e.g., 35k keys), use indexes: 0 to index all containers: stringify ( data , { indexes : 0 } ) ; Resources rx.run — live web viewer, paste RX or JSON to inspect docs/rx-format.md — full format spec with grammar and railroad diagrams docs/cursor-api.md — low-level zero-allocation cursor API samples/ — example datasets (route manifest, RPG state, emoji metadata, sensor telemetry)