Skip to content
HN On Hacker News ↗

@codemix/graph - codemix

▲ 166 points 47 comments by phpnode 5w ago HN discussion ↗

Pangram verdict · v3.3

We believe that this document is primarily AI-generated with some human-written content

62 %

AI likelihood · overall

AI
18% human-written 82% AI-generated
SEGMENTS · HUMAN 1 of 5
SEGMENTS · AI 4 of 5
WORD COUNT 1,101
PEAK AI % 100% · §1
Analyzed
Apr 21
backend: pangram/v3.3
Segments scanned
5 windows
avg 220 words each
Distribution
18 / 82%
human / AI fraction
Verdict
AI
Pangram v3.3

Article text · 1,101 words · 5 segments analyzed

Human AI-generated
§1 AI · 100%

Plane route demoGlobal airline routes demoLoad a snapshot of real airline routes into the graph and query it with TypeScript.Live demoAdd your face to the wallPowered by @codemix/graph and @codemix/y-graph-storage — a real graph database, synced via a Yjs CRDT across every open tab. Add yourself, rearrange people, draw connections.InstallationInstall the package from npm — no native dependencies, runs anywhere Node or a bundler can.$ pnpm add @codemix/graphNote: This is alpha-quality software. We use it in production at codemix and it works well for our use cases, but please be careful using it with your own data.Define your schemaDescribe vertices, edges, and indexes in a plain object. Property types flow through every query, traversal, and mutation — no casts, no runtime surprises.import { Graph, GraphSchema, InMemoryGraphStorage } from "@codemix/graph"; import { z } from "zod";

const schema = { vertices: { User: { properties: { email: { type: z.email(), index: { type: "hash", unique: true } }, name: { type: z.string() }, }, }, Repo: { properties: { name: { type: z.string() }, stars: { type: z.number() }, }, }, }, edges: { OWNS: { properties: {} }, FOLLOWS: { properties: {} }, }, } as const satisfies GraphSchema;

const graph = new Graph({ schema, storage: new InMemoryGraphStorage() });→Any Standard Schema library — Zod, Valibot, ArkType, or your own.→Validated on every mutation — properties are checked on addVertex, addEdge, and updateProperty.→Indexes declared inline — hash, B-tree, and full-text; built lazily and maintained incrementally.Add some dataVertices and edges are added through the graph instance.

§2 AI · 100%

Property arguments are checked against your schema at both compile time and runtime.// add vertices — args are typed to each label's property schema const alice = graph.addVertex("User", { name: "Alice", email: "alice@example.com" }); const bob = graph.addVertex("User", { name: "Bob", email: "bob@example.com" }); const myRepo = graph.addVertex("Repo", { name: "my-repo", stars: 0 });

// add edges graph.addEdge(alice, "OWNS", myRepo, {}); graph.addEdge(bob, "FOLLOWS", alice, {});

// read properties — types come from the schema alice.get("name"); // string myRepo.get("stars"); // number

// update in place graph.updateProperty(myRepo, "stars", 42); // or via the element itself myRepo.set("stars", 42);Write type-safe queriesA Gremlin-style traversal API — familiar step names, but every label, property key, and hop is checked by TypeScript against your schema.Start a traversalimport { GraphTraversal } from "@codemix/graph";

const g = new GraphTraversal(graph);

for (const path of g.V().hasLabel("User")) { path.value.get("name"); // string ✓ path.value.get("email"); // string ✓ }Filter by property// exact match or predicate const [alice] = g.V() .hasLabel("User") .has("email", "alice@example.com");

const seniors = g.V() .hasLabel("User") .where((v) => v.get("name").startsWith("A"));Traverse edges// follow OWNS edges from User → Repo for (const path of g.V() .hasLabel("User") .has("email", "alice@example.com") .out("OWNS").hasLabel("Repo")) { path.value.get("stars"); // number — typed from Repo's schema }Label and select// capture vertices at multiple hops and project them together for (const { user, repo } of g.V() .hasLabel("User").as("user") .out("FOLLOWS")

§3 AI · 100%

.out("OWNS").hasLabel("Repo").as("repo") .select("user", "repo")) { console.log( user.value.get("name"), // string repo.value.get("stars"), // number ); }Offline-first sync and realtime collaborationSwap InMemoryGraphStorage for YGraph and the entire graph lives in a Yjs CRDT document. Every traversal, Cypher query, and index works unchanged — you just get conflict-free sync on top.Plug in a providerimport * as Y from "yjs"; import { WebsocketProvider } from "y-websocket"; import { YGraph } from "@codemix/y-graph-storage";

const doc = new Y.Doc(); const graph = new YGraph({ schema, doc });

// Connect any Yjs provider — sync happens automatically. // Every peer that joins the room sees the same graph. const provider = new WebsocketProvider("wss://my-server", "graph-room", doc);Subscribe to fine-grained changes// Events fire for local and remote mutations alike const unsubscribe = graph.subscribe({ next(change) { // change.kind is one of: // "vertex.added" | "vertex.deleted" // "edge.added" | "edge.deleted" // "vertex.property.set" | "vertex.property.changed" console.log(change.kind, change.id); }, });Live queries// Wraps any traversal and re-fires when the result set could change const topRepos = graph.query((g) => g.V().hasLabel("Repo").order("stars", "desc").limit(10) );

const unsubscribe = topRepos.subscribe({ next() { for (const path of topRepos) { console.log(path.value.get("name"), path.value.get("stars")); } }, });

// Adding or updating a Repo elsewhere — even from a remote peer — // triggers the subscriber automatically.

§4 AI · 100%

graph.updateProperty(myRepo, "stars", 99);Collaborative property typesimport { ZodYText, ZodYArray } from "@codemix/y-graph-storage"; import { z } from "zod";

// Declare Y.Text / Y.Array / Y.Map properties in the schema const schema = { vertices: { Document: { properties: { title: { type: ZodYText }, // collaborative string tags: { type: ZodYArray(z.string()) }, // collaborative array }, }, }, edges: {}, } as const satisfies GraphSchema;

// Plain values are auto-converted — no need to construct Y.* manually const doc = graph.addVertex("Document", { title: "Hello", tags: ["crdt"] });

// Mutate in place — all peers see the change with no conflicts doc.get("title").insert(5, ", world"); doc.get("tags").push(["graph"]);Cypher queries for APIs and LLMsThe same graph is queryable via a Cypher-compatible string language — ideal for exposing data to LLMs via an MCP server, or accepting ad-hoc queries from external clients without bundling a traversal library.Parse and executeimport { parseQueryToSteps, createTraverser } from "@codemix/graph";

const { steps, postprocess } = parseQueryToSteps(` MATCH (u:User)-[:OWNS]->(r:Repo) WHERE r.stars > 100 RETURN u.name, r.name ORDER BY r.stars DESC LIMIT 10 `);

const traverser = createTraverser(steps); for (const row of traverser.traverse(graph, [])) { console.log(postprocess(row)); // { u: { name: "Alice" }, r: { name: "my-repo" } } }Parameterised queries// Pass parameters to avoid string interpolation const { steps, postprocess } = parseQueryToSteps(` MATCH (u:User { email: $email })-[:OWNS]->(r:Repo)

§5 Human · 5%

RETURN r.name, r.stars `);

const traverser = createTraverser(steps); const rows = Array.from( traverser.traverse(graph, [{ email: "alice@example.com" }]) ).map(postprocess);Mutations// CREATE, MERGE, SET, DELETE are all supported const { steps } = parseQueryToSteps(` MATCH (r:Repo { name: $name }) SET r.stars = r.stars + 1 `);

createTraverser(steps).traverse(graph, [{ name: "my-repo" }]);

// Enforce read-only — throws ReadonlyGraphError on any write clause const { steps: safeSteps } = parseQueryToSteps(query, { readonly: true });License & HistoryThis package is licensed under the MIT license.It was orignally written as a research project by Charles Pick, founder of codemix and author of the infamous ts-sql demo. Later, when we were building codemix we needed a structured knowledge graph, so we adapted the code, added Y.js support and later, Opus 4.5 added a Cypher-like query language.Star on GitHubWhile you're hereA single source of truth for your product.For humans and AI.codemix captures what you actually mean — your business domain, your user flows, the concepts, the constraints — and keeps it in sync with your codebase automatically.Change your product through chat, diagrams, or collaborative editing. Steer coding agents through development and review code with real understanding. Every agent on your team shares the same context.Create something completely new, or import your existing codebase to get started.Build something brand newTry codemix for free, no credit card required.FREE