Sno Station
Sno Station은 AI 에이전트를 하나의 팀으로 묶는 오픈소스 워크스테이션으로, 로컬 머신에서 에이전트 협업을 가능하게 함
하나의 모델로 속성 그래프 설계 시 LadybugDB DDL·Neo4j 제약·SHACL 형태·OWL 온톨로지를 동시에 생성
Design a property graph once. Generate LadybugDB DDL, Neo4j constraints, SHACL shapes and an OWL ontology from the same model.
플러그인TypeScript · CypherGitHub @Volland온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Design a labeled property graph once. Generate LadybugDB DDL, Neo4j constraints, SHACL shapes and an OWL ontology from it. VS Code extension + CLI.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
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.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.