BendScript is a JSON document format where every span can carry a typed edge to another document, span, or external URI. Documents are content-addressable, edges are span-addressable, and the parser round-trip holds for every document in the v0.1 corpus.
install
— one package, no build step
// 1. install the reference framework npm install @bendscript/core // 2. parse, validate, hash a document import { parseAndNormalize, computeDocumentId } from "@bendscript/core"; const doc = parseAndNormalize(readFileSync("note.bend.json", "utf8")); const id = await computeDocumentId(doc); // → bagaaie... (CIDv1, multicodec=json, sha2-256)
this is the substrate — not a screenshot. paste a document, see live validation, watch link marks expand into edges, copy the canonical form. all client-side; no server sees your text.
where it fits
Most document formats in this neighborhood treat the graph as an afterthought — or skip it entirely. BendScript inverts the relationship: the graph is the document. Prose is one projection of it.
Markdown links are untyped strings inside a string.
BendScript links carry a predicate
(cites, supports,
contradicts...) and resolve to spans,
not just URLs. Round-trip a doc through an LLM and
the graph survives.
RDF can express any graph, but the document is metadata about a triple store. BendScript keeps the document as the unit; edges are attached to spans of text, not synthesized from out-of-band metadata.
Editor schemas live in editor land. BendScript is host-coupling-free: an Elixir, Rust, or plain-HTML implementation must produce the same id for the same document. The reference is TypeScript; the spec is the contract.
primitives
The whole protocol is six things and one invariant. The
invariant:
parse(serialize(parse(d))) === parse(d)
for every conforming document.
a JSON object with blocks, edges, vocabulary, meta, and a content-addressable id. the id is a CIDv1 over JCS-canonical bytes — same blocks + edges, same id.
{ "bendscript": "0.1", "id": "bagaaie...", "vocabulary": "core", "blocks": [...], "edges": [...] }
paragraph, heading, list, list-item, quote, code, embed, divider — or any vocabulary-defined kind. blocks contain spans (or other blocks, for lists).
{ "id": "blk-1", "kind": "paragraph", "spans": [...] }
a chunk of text with an id. every edge target lands
on a span:
bend:<doc>#blk-1.spn-2. spans are
why edges can attach to "this exact phrase" not just
"this document."
{ "id": "spn-2", "text": "the memory loop", "marks": [...] }
bold, italic,
code, link. only
link carries data — a target URI
and (optionally) a predicate. typed link marks
expand deterministically into edges.
{ "kind": "link", "target": "bend:bafy...", "predicate": "cites" }
subject → predicate → object, where either endpoint can be a span URI. nine core predicates plus any namespaced predicate from a vocabulary.
{ "subject": "bend:<d>#blk-1", "predicate": "supports", "object": "bend:<e>#blk-3" }
namespace your own block kinds, predicates, and meta fields without forking the protocol. five reserved vocabularies ship in v0.1; anyone can register more.
{ "vocabulary": "bendscript.memory.v1", "meta": { /* vocab fields */ } }
vocabularies
Vocabularies are how BendScript stays small at the core and
expressive at the edges. The protocol defines a tiny set;
each portfolio product reserves a namespace and adds the
fields it needs. v0.1 ships these five with
bendscript.memory.v1 as the load-bearing
adopter (§14.3.1).
the irreducible vocabulary. paragraph, heading,
list, quote, code, embed, divider; nine edge
predicates: cites,
supports, contradicts,
derives-from, supersedes,
transcludes, responds-to,
defines, exemplifies.
knowledge nodes, claims, evidence chains. four
reserved predicates (derived-from,
contradicts-belief,
consolidated-into,
routed-from) and four meta fields
(confidence, topology,
provenance,
retrieval-context). the §14 gating
commitment.
claims, warrants, rebuttals. structured argumentation graphs that compose with deliberatic's deliberation engine. round-trippable claim trees with provenance-preserving rewrites.
requirements, MUST/SHOULD/MAY clauses, traceable spec sections. each clause is a span with edges to the implementations and tests that satisfy it.
tile-bound prose: a paragraph anchored to a room on a runefort floor. the document is the reading surface; the floor is the spatial index.
Write your own at any time — namespace it freely
(com.example.my-vocab.v1), declare it in
vocabulary, ship. The protocol does not require
registration; unknown vocabularies degrade gracefully.
verification
BendScript v0.1 is a protocol that makes one falsifiable claim: the parser round-trip is deterministic across every document in a 20-doc corpus. That holds today. The other two gating items (LLM round-trip on real models; Graphonomous adoption) remain open.
for engineers
BendScript is a small declarative protocol. The reference
framework @bendscript/core is TypeScript on
Node 20+. Documents are JSON; canonicalization is RFC 8785
(JCS); ids are CIDv1 with the json multicodec. Independent
of the rest of the [&] stack — usable by them,
never required.
Open the playground. Paste a document. Watch link marks expand
into edges. Copy the canonical form. Then reach for
@bendscript/core and start round-tripping your own.