Quick Start
Install Omnigraph, define a schema, load data, run a query, branch a change, and merge it back.
This guide walks you through a complete Omnigraph workflow: defining a typed schema, loading graph data, running a read query, making a change on a branch, and merging that branch back into main.
Install
Build the Omnigraph CLI from source:
git clone https://github.com/ModernRelay/omnigraph.git
cd omnigraph
cargo build --release -p omnigraph-cliThe compiled binary is at target/release/omnigraph.
Define a schema
Create a file called schema.pg:
node Task {
slug: String @key
title: String @index
status: enum(pending, in_progress, completed)
}
edge DependsOn: Task -> TaskThis schema defines one node type and one edge type. Each Task has a stable key (slug), a searchable title, and a status enum. The DependsOn edge captures task dependencies directly in the graph.
Initialize a repository
Create a new graph repository at ./my-graph, using your schema:
omnigraph init --schema schema.pg ./my-graphLoad data
Create a file called data.jsonl:
{"type": "Task", "data": {"slug": "auth", "title": "Finish auth flow", "status": "pending"}}
{"type": "Task", "data": {"slug": "api", "title": "Ship API endpoint", "status": "pending"}}
{"type": "Task", "data": {"slug": "frontend", "title": "Connect frontend", "status": "pending"}}
{"edge": "DependsOn", "from": "api", "to": "auth"}
{"edge": "DependsOn", "from": "frontend", "to": "api"}Each line is either a node or an edge. Edge records reference nodes by their @key value (slug). Load the file:
omnigraph load ./my-graph --data data.jsonlWrite a query and a mutation
Create a file called queries.gq:
query unblocked_tasks() {
match {
$t: Task { status: "pending" }
not {
$t dependsOn $dep
$dep.status != "completed"
}
}
return { $t.slug, $t.title }
}
query mark_completed($slug: String) {
update Task set {
status: "completed",
}
where slug = $slug
}Run the query on main
omnigraph read ./my-graph \
--query queries.gq \
--name unblocked_tasks \
--json[
{ "slug": "auth", "title": "Finish auth flow" }
]Only auth is unblocked. api depends on auth, and frontend depends on api.
Create a branch
omnigraph branch create --uri ./my-graph --from main finish-authThe branch starts as an exact copy of main. Any changes you make on it are isolated until you merge.
Apply a change on the branch
omnigraph change ./my-graph \
--query queries.gq \
--name mark_completed \
--params '{"slug": "auth"}' \
--branch finish-auth \
--jsonVerify the branch state
omnigraph read ./my-graph \
--query queries.gq \
--name unblocked_tasks \
--branch finish-auth \
--json[
{ "slug": "api", "title": "Ship API endpoint" }
]Because auth is completed on finish-auth, api is now unblocked. main still returns auth.
Merge back to main
omnigraph branch merge --uri ./my-graph finish-auth --into main --jsonAfter the merge, main reflects the completed auth task and api becomes the next unblocked task.