Reference
Commands, settings, shortcuts and the validation rules, in one place.
Commands
All commands are under the ORM category in the Command Palette.
| Command | Description |
|---|---|
ORM: New ORM Model | Create a starter .orm.json and open the diagram |
ORM: Import NORMA (.orm) File | Convert a NORMA / ORM 2 XML file |
ORM: Import Model (NORMA, FBM, Ossie, UMS) | Convert any supported interchange document — see File formats |
ORM: Export Model As (NORMA, FBM, Ossie, UMS) | Write the model out in an interchange format |
ORM: Derive Model from Example Data (CSV) | Propose a first-draft model from a table of examples |
ORM: Verbalize Model | Full FORML verbalization as a Markdown document |
ORM: Show Relational Mapping | The mapped tables as a Markdown table |
ORM: Generate Relational Schema (SQL DDL) | SQL DDL in a new editor |
ORM: Generate Property Graph Schema (LadybugDB) | LadybugDB Cypher DDL in a new editor |
ORM: Export Diagram as SVG | Save the diagram as SVG |
ORM: Export Diagram as PNG | Save the diagram as a 2× PNG |
ORM: Auto-Layout Diagram | Re-arrange the diagram |
ORM: Open Model Source (JSON) | Open the model as text |
Settings
| Setting | Default | Description |
|---|---|---|
orm.ddl.dialect | postgres | SQL dialect: postgres, sqlserver, mysql, sqlite or ansi |
orm.ddl.quoteIdentifiers | false | Always quote generated identifiers |
orm.graph.subtypeStrategy | nodeTable | nodeTable gives each subtype its own label plus IS_A; absorb folds it into the supertype |
orm.graph.ifNotExists | false | Emit IF NOT EXISTS so the script can be re-run |
orm.validation.enabled | true | Report model problems in the Problems panel |
orm.verbalization.mode | forml | forml or plainer English |
orm.diagram.snapToGrid | true | Snap shapes to the grid while dragging |
orm.diagram.gridSize | 10 | Grid size in pixels |
orm.diagram.showGrid | true | Show the grid |
Keyboard and mouse
| Action | Binding |
|---|---|
| Select tool | V |
| Entity type / value type | E / T |
| Unary / binary / ternary fact type | 1 / 2 / 3 |
| Subtype link / connect role | S / C |
| Zoom to fit | F |
| Auto-layout | Ctrl/Cmd + Alt + L |
| Delete selection | Delete |
| Undo / redo | Ctrl/Cmd + Z / Ctrl/Cmd + Shift + Z |
| Add to selection | Shift + click |
| Rename in place | Double-click a shape |
| Pan | Middle-drag, or drag empty canvas |
| Zoom | Scroll wheel |
| Cancel / clear selection | Esc |
Supported constraints
| Constraint | Applies to | Drawn as |
|---|---|---|
| Uniqueness (internal) | Roles of one fact type | Bar over the roles |
| Uniqueness (external) | Roles across fact types | Circled bar with dashed links |
| Preferred identifier | A uniqueness constraint | Double bar or double circle |
| Mandatory (simple) | One role | Dot where the role meets its object type |
| Mandatory (disjunctive) | Several roles of one type | Dot linked to each role |
| Frequency | One or more roles | Bar annotated with the range |
| Ring | Two roles played by one type | Circled ring glyph |
| Subset / exclusion / equality | Two role sequences | Circled ⊆, ✕ or = with dashed links |
| Value | Object type or role | {'M', 'F'} beside the shape |
| Cardinality | Object type or role | Properties panel |
| Subtype exclusion / exhaustion | Subtypes of one supertype | Properties panel |
Every constraint carries a modality: alethic (cannot be violated) or deontic (should not be), which the verbalizer renders as It is necessary that… versus It is obligatory that…
Validation rules
Problems appear in VS Code's Problems panel with the codes below, and the offending shape is highlighted on the diagram.
| Code | Severity | Meaning |
|---|---|---|
no-reference-scheme | Error | An entity type has no reference mode, preferred identifier, objectification or supertype |
missing-uniqueness | Error | A fact type has no uniqueness constraint |
uniqueness-too-narrow | Error | An internal uniqueness constraint spans fewer than n−1 roles, so the fact type is not elementary |
unattached-role | Error | A role is not connected to an object type |
reading-arity-mismatch | Error | A reading's placeholders do not match the fact type's roles |
duplicate-object-type-name | Error | Two object types share a name |
subtype-cycle | Error | Subtype links form a cycle |
subtype-kind-mismatch | Error | An entity type and a value type are linked by subtyping |
ring-incompatible-roles | Error | A ring constraint spans roles with no common object type |
set-constraint-length | Error | Compared role sequences have different lengths |
set-constraint-compatibility | Error | Compared roles are played by incompatible types |
bad-frequency-range | Error | A frequency or cardinality range is impossible |
unused-object-type | Warning | An object type plays no roles and is not part of a subtype graph |
frequency-is-uniqueness | Warning | A frequency of exactly 1 should be a uniqueness constraint |
redundant-spanning-uniqueness | Warning | A spanning uniqueness constraint is implied by a narrower one |
ambiguous-identification-path | Warning | A subtype has several supertypes but no single identification path |
implied-mandatory | Warning | A subset constraint from mandatory roles makes the superset roles mandatory |
Turn validation off with orm.validation.enabled if you want to sketch freely.
Command line
The model is a text file, so a build can check it. factum runs the same model,
verbalizer, validator and mappers the editor does.
| Command | Description |
|---|---|
factum validate <model> | Report problems. --format github annotates a CI run; --strict treats warnings as errors |
factum verbalize <model> | FORML sentences. --population also reads the sample facts back |
factum ddl <model> | SQL DDL, with --dialect |
factum graph <model> | LadybugDB Cypher DDL |
factum diff <before> <after> | What the model now says. --format markdown, --exit-code |
factum drift <model> <schema.sql> | Where an existing database disagrees, with the reconciling statements |
factum convert <input> | Read or write any interchange format with --to |
factum derive <table.csv> | A first-draft model from example data |
validate exits 1 on a blocking error, 2 on a usage or IO failure, and 0 otherwise, so
a shell can tell a broken model from a broken invocation.
Pull request check
The bundled GitHub Action validates a model and comments with the sentences that changed.
- uses: Volland/factum-orm@v0
with:
model: model/domain.orm.json
base: /tmp/base.orm.json # the same file from the base branch
strict: 'true'
MCP server
factum-mcp exposes the model to a coding agent over stdio, so Claude Code, Copilot or
any MCP client can read the conceptual schema instead of inferring it from the tables.
{ "mcpServers": { "factum": { "command": "factum-mcp" } } }
Tools: read_model, verbalize_model, validate_model,
generate_schema, diff_models, detect_drift,
read_population and apply_model. Everything is read-only except the
last, which validates first and refuses to write a model with blocking errors.