Sno Station
Sno Station is your agents' workstation: open-source software that turns the AI agents you already run into one squad on your own machine. Two heads are better than one, and they get better with every
Design a property graph once. Generate LadybugDB DDL, Neo4j constraints, SHACL shapes and an OWL ontology from the same model.
PluginsTypeScript · CypherGitHub @VollandOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Design a labeled property graph once. Generate LadybugDB DDL, Neo4j constraints, SHACL shapes and an OWL ontology from it. VS Code extension + CLI.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Design a property graph once. Generate every schema from it.
A VS Code extension and CLI for authoring Labeled Property Graph schemas as text, viewing them
as ERD-like diagrams, and generating database DDL and RDF artifacts from a single model.Read the full README ↗A VS Code extension and CLI for authoring Labeled Property Graph schemas as text, viewing them as ERD-like diagrams, and generating database DDL and RDF artifacts from a single model.
Full feature tour: https://volland.github.io/lpg-modeler/
The canvas opens beside the model file, in the manner of Markdown preview. Every box is a node type, every row a property, and every action on it a targeted edit to the YAML.
This is fleet.lpg.yaml, one of the downloadable examples
below. Asset and Vehicle are abstract — drawn with a dashed border and an abstract
badge, and emitting no table. Truck sits three levels down: assetTag arrives from
Asset, vin from Vehicle, and each inherited row names its source with ↑. Properties
that came from a mixin are marked ◇ instead, because a supertype and a bag of properties
are not the same claim about a type. STATIONED_AT is declared once on Asset and drawn
on Asset alone: repeating it on four subtypes would suggest four declarations where the
model has one.
Selecting a type shows what a diagram box has no room for. Extends is a dropdown over the
model's own types. Mixins are checkboxes, not a parent dropdown — applying one is set
membership, and a type may apply several. Under Edges, DRIVES and STATIONED_AT are
marked ↑Vehicle and ↑Asset: they are declared on an ancestor and reach this type through
it. That is the reading a modeller actually needs — what can this type relate to — and it
is a list rather than a picture.
A mixin has no box on the canvas, because it is not a type. It gets the panel instead:
its properties, and every type applying it, so a change to Timestamped shows what it
would touch before you make it. Renaming one rewrites the mixins: list of every type that
names it, as a targeted edit.
Why the distinction is enforced rather than blurred: conflating reuse with subtyping
produces a hierarchy shaped by which properties happen to travel together rather than by
what a thing is. createdAt on twenty types does not make twenty subtypes of a
Timestamped. See the metamodel notes.
Five complete models, each checked in continuous integration — a test resolves every one of them and generates all nine targets, so the file you download is the file the test checked.
| Model | Shows |
|---|---|
social.lpg.yaml | The starter: an abstract parent contributing a key, a mixin, and an edge with an abstract endpoint |
fleet.lpg.yaml | Inheritance and mixins: a three-level abstract hierarchy, three mixins applied at different levels, and an edge declared once on the root |
catalog.lpg.yaml | Enums, list-valued properties, a composite key, and an open type — where the targets start disagreeing |
kinship.lpg.yaml | Endpoint bounds: exactly two parents, which no named multiplicity can express |
booking.lpg.yaml | Value bounds, patterns, named constraints, and the raw SHACL escape hatch |
Save one as <name>.lpg.yaml in a workspace — the extension matches on that suffix — then:
npx lpg-modeler-cli check fleet.lpg.yaml
npx lpg-modeler-cli emit fleet.lpg.yaml --target ladybug --target shacl --out ./schema
Or start from a schema you already have, reading the shapes graph and the ontology together because each carries what the other cannot:
npx lpg-modeler-cli import domain.shacl.ttl domain.owl.ttl --out domain.lpg.yaml
Or read a LadybugDB database you already run. It is opened read-only, and reading it needs the engine's runtime, which the CLI does not bundle:
npx -p lpg-modeler-cli -p @ladybugdb/[email protected] lpg import graph.lbdb --out domain.lpg.yaml
Or read a running database, and apply a reviewed script back to it. Every database target can
now be read and deployed to: LadybugDB by path, Memgraph and Neo4j over Bolt, FalkorDB over
Redis. Which engine a bolt:// URI is comes from the instance, not the URI — Memgraph answers
Neo4j's own SHOW CONSTRAINTS with an empty list rather than an error, so guessing would
report an empty schema and no failure:
npx -p lpg-modeler-cli -p [email protected] lpg import bolt://localhost:7687 --out domain.lpg.yaml
npx -p lpg-modeler-cli -p [email protected] lpg apply domain.memgraph.cypher --target memgraph --uri bolt://localhost:7687
npx -p lpg-modeler-cli -p [email protected] lpg apply domain.neo4j.cypher --target neo4j --uri bolt://localhost:7687
npx -p lpg-modeler-cli -p [email protected] lpg import redis://localhost:6379 --out domain.lpg.yaml
npx -p lpg-modeler-cli -p @ladybugdb/[email protected] lpg apply domain.ladybug.cypher --target ladybug --database graph.lbdb
Each connecting command loads its own driver — neo4j-driver, redis or @ladybugdb/core —
as an optional peer, so a CI run that only checks and generates downloads none of them.
Browse them with commentary: https://volland.github.io/lpg-modeler/examples.html
From the VS Code Marketplace:
code --install-extension pavlyshyn.lpg-modeler
The CLI, for continuous integration:
npx lpg-modeler-cli check model/domain.lpg.yaml
npx lpg-modeler-cli emit model/domain.lpg.yaml --target ladybug --out schema
A monorepo of three packages.
| Package | Holds |
|---|---|
packages/core | Parsing, the intermediate representation, resolution, validation, targeted edits, every generator, and the importers |
packages/cli | The lpg command, wrapping core for continuous integration |
packages/vscode | The extension: webview canvas, diagnostics, commands |
core must never import vscode — enforced by an ESLint rule and by a test that scans the
source. That single rule is what keeps generator tests runnable in plain Node with no editor
harness. See the design notes.
npm install
npm run build # builds core, then cli, then the extension and its webview
npm test # vitest, across all packages
npm run lint
To run the extension from source, open the repository in VS Code and launch the Run Extension target, or package it:
cd packages/vscode
npx @vscode/vsce package --no-dependencies
The extension bundle is self-contained — esbuild inlines @lpg/core into
out/extension.js, so --no-dependencies is correct rather than a shortcut.
Every generator has golden-file tests for output stability. The Ladybug target additionally executes its generated DDL against an in-process LadybugDB instance and asserts that the declared constraints really do reject invalid data — a golden file alone only proves that output has not changed, not that it is valid.
Architecture and design intent live in lat.md/, a cross-linked knowledge graph
maintained with lat.md. Run lat check before opening
a pull request. The published website is generated from docs/.
MIT — see LICENSE.