notepack
notepack is a Rust library and CLI for encoding and decoding nostr notes into a compact binary format.
It ships with:
- π¦ A Rust crate β for embedding notepack logic into apps, relays, or tooling.
- π» A CLI tool β for piping JSON β
notepack_β¦strings in scripts.
π What is notepack?
notepack is a binary serialization for Nostr βeventsβ (Note), plus a recognizable string form.
It aims to:
- Shrink payloads using unsigned LEB128 (βvarintβ) integers.
- Store note fields (id, pubkey, sig) and hex tag payloads as raw bytes.
- Preserve UTFβ8 for text fields.
- Provide a copyβpasteable string starting with
notepack_+ Base64 (RFC 4648, no padding).
π See SPEC.md for the full format specification.
β¨ Features
- β CLI tool: Turn JSON Nostr events into compact strings or back again.
- β Compact: Every integer is ULEB128 varint, tags are taggedβvarint.
- β 50% size reduction Many large events like contact lists see a 50% reduction in size
- β Simple So simple, I'm proposing it as the candidate for nostr's canonical binary representation
- β Streaming parser: No massive allocations; parse incrementally.
Example
$ notepack <<<'{"id": "f1e7bc2a9756453fcc0e80ecf62183fa95b9a1278a01281dbc310b6777320e80","pubkey": "7fe437db5884ee013f701a75f8d1a84ecb434e997f2a31411685551ffff1b841","created_at": 1753900182,"kind": 1,"tags": [],"content": "hi","sig": "75507f84d78211a68f2f964221f5587aa957a66c1941d01125caa07b9aabdf5a98c3e63d1fe1e307cbf01b74b0a1b95ffe636eb6746c00167e0d48e5b11032d5"}'
notepack_AfHnvCqXVkU/zA6A7PYhg/qVuaEnigEoHbwxC2d3Mg6Af+Q321iE7gE/cBp1+NGoTstDTpl/KjFBFoVVH//xuEF1UH+E14IRpo8vlkIh9Vh6qVembBlB0BElyqB7mqvfWpjD5j0f4eMHy/AbdLChuV/+Y262dGwAFn4NSOWxEDLVlsmpxAYBAmhpAA
- json string: 363 bytes
- notepack string: 124 bytes raw, 196 base64-encoded
For large contact lists, you can crunch them down from 74kb to about 36kb.
π¦ Usage (Library)
Encoding
use ;
let note = Note ;
let encoded = pack_note_to_string.unwrap;
println!; // => notepack_AAECAw...
Streaming Decode
use ;
let b64 = "notepack_..."; // from wire
let bytes = decode.unwrap;
let parser = new;
for field in parser
π» CLI Usage
The binary is also called notepack.
Encode JSON β notepack string
|
Decode notepack string β JSON
|
π Project Structure
src
βββ SPEC.md # Full binary format spec
βββ error.rs # Unified error type for encoding/decoding
βββ lib.rs # Crate entrypoint
βββ main.rs # CLI tool: JSON β notepack
βββ note.rs # `Note` struct (Nostr event model)
βββ parser.rs # Streaming `NoteParser`
βββ stringtype.rs # String vs raw byte tags
βββ varint.rs # LEB128 varint helpers
π License
MIT β do whatever you want, but attribution is appreciated.