LPG Modeler
Reference

The same checks, without an editor

lpg runs the resolution, validation and generation the extension runs, in plain Node. That is what lets a pull request be gated on the model being valid.

lpg - labeled property graph modeler

Usage:
  lpg check <model.lpg.yaml>
  lpg emit  <model.lpg.yaml> --target <gql|ladybug|linkml|neo4j|owl|pgschema|shacl> [options]
  lpg ids   <model.lpg.yaml>        assign any missing stable element ids
  lpg targets

Options:
  --target <name>       generation target (repeatable)
  --out <dir>           write artifacts to this directory instead of stdout
  --edition <name>      neo4j edition: community (default) or enterprise

check

Resolves the model and its imports, validates it, and prints every diagnostic as file:line:column severity code: message. Exits 1 when the model has errors, 0 otherwise — warnings alone do not fail the run.

$ lpg check social.lpg.yaml
0 error(s), 0 warning(s)

emit

Generates one or more targets. --target is repeatable. Without --out, artifacts go to stdout; with it, each is written as <model-stem>.<target>.<ext> in that directory, which is created if it does not exist.

$ lpg emit social.lpg.yaml --target ladybug --target shacl --out ./schema
schema/social.ladybug.cypher
schema/social.shacl.ttl

The standards targets work the same way, and are what you reach for when the model has to be read by something this project does not own:

$ lpg emit social.lpg.yaml --target gql --target pgschema --target linkml --out ./schema
schema/social.gql.gql
schema/social.pgschema.pgs
schema/social.linkml.yaml

A model with errors produces nothing at all — the command reports them and exits 1 rather than writing a partial artifact. Downgrade warnings are printed to stderr after the artifact list, and each one is also recorded as a comment inside the artifact:

$ lpg emit social.lpg.yaml --target ladybug --out ./schema
schema/social.ladybug.cypher
social.lpg.yaml:26:7 warning [ladybug] downgrade-required: Property
'Person.email' is required, which LadybugDB cannot enforce: it has no
NOT NULL and only the primary key is non-null.

ids

Assigns a stable element id to every node type, edge type, property and mixin that lacks one, editing the model file in place. Useful after hand-writing a model, or after a merge. Existing ids are never rewritten.

$ lpg ids social.lpg.yaml
assigned 14 id(s) in /work/social.lpg.yaml

targets

Prints the registered target names, one per line.

$ lpg targets
gql
ladybug
linkml
neo4j
owl
pgschema
shacl

Options

--target <name>
Which generator to run. Repeat the flag to run several in one pass. An unknown name is an error naming the ones that exist.
--out <dir>
Write artifacts into this directory instead of stdout. Created recursively if missing.
--edition <community|enterprise>
Neo4j edition. Community — the default — cannot enforce existence or node key constraints, so under it those become downgrades and comments.

Exit codes

CodeWhen
0Success. Warnings may still have been printed.
1The model has errors, a file could not be read, or a generator failed.
2Usage error — an unknown flag, a missing target, or no model path.

In continuous integration

Gate the branch on the model staying valid, and on the committed schema staying in sync with it:

name: schema
on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '22' }
      - run: npm ci

      # Fails the build on any model error.
      - run: npx lpg-modeler-cli check model/domain.lpg.yaml

      # Regenerate and fail if the committed artifacts drifted.
      - run: npx lpg-modeler-cli emit model/domain.lpg.yaml --target ladybug --target shacl --out schema
      - run: git diff --exit-code schema

The second step is the one that matters over time. It turns "someone forgot to regenerate the DDL" from a thing you discover during an incident into a red build.

Where to go next