Getting Started
This chapter walks you through your first definition: you model a small turn indicator function, validate the definition, and write a configuration against it. At the end you have the complete edit and validate loop running.
What a Definition Developer Builds
Confµgami separates configuration into two file kinds:
-
A definition file (
.def.json5) describes the configuration schema model: which elements exist, their types, value ranges, documentation, and how configuration files may be split and merged. Definitions are owned by the software component author, for example the developer of an ECU function. -
A configuration file (
.cfg.json5) holds the actual configuration data. Configurations are written by the users of your component, usually with IDE support (completion, hover, diagnostics) that Confµgami derives from your definition.
Everything the configuration author experiences, from completion over value range checks to generated code, is derived from the definition. Writing a good definition is therefore an API design task: you are building the contract between your software and its integrators.
Prerequisites
-
The
cfuexecutable on yourPATH(in this repository:cargo build, the binary istarget/debug/cfu). -
Any editor. For the full experience use an IDE with the Confµgami LSP integration (see the user manual, IDE setup).
Step 0: Scaffold a Workspace (Optional)
If you want a ready-made starting point, run cfu init in an empty directory.
It creates the workspace .confu, an .editorconfig, and an example definition plus configuration, then formats and validates them.
Use cfu init --name MyProduct to pick the definition name.
Prefer to learn the pieces by hand?
Skip this step and follow the rest of the chapter, which builds a turn indicator definition from scratch.
Step 1: Write the Definition
Create a file named TurnIndicator.def.json5.
The file name is free, the .def.json5 suffix is what makes it a definition file.
Start with the document header:
$definitionSpecVersion: "1.0",
definitionName: "TurnIndicator",
definitionVersion: "1.0",
configurationFileMode: "SingleFile",
title: "Turn indicator",
description: "Turn indicator function configuration of a body ECU.",
-
$definitionSpecVersionstates which version of the definition language the file uses. It is checked against the Confµgami version, currently"1.0". -
definitionNamenames the definition. Configuration files bind to it by this name, and it is the root of all type paths (TurnIndicator::…). It must be UpperCamelCase, like all other types. -
definitionVersionversions your model, inmajor[.minor[.patch]]form. -
configurationFileModedecides how many configuration files may exist and whether they merge.SingleFileis the simplest mode, see Multi-file configurations for the others. -
titleanddescriptiondocument the definition for the configuration author. Descriptions support Markdown.
Then add the content below the definition key:
indicator: {
title: "Turn indicator function",
description: "Settings of the direction indicator flasher.",
multiplicity: "1..1",
entity: {
flashFrequency: {
title: "Flash frequency",
description: "How often the indicator lamps flash per second.",
multiplicity: "1..1",
u8: {
min: 1,
max: 3,
unit: "Hz"
}
},
dimmingLevel: {
description: "PWM duty cycle for the indicator lamps in percent.",
u8: {
min: 0,
max: 100,
default: 100,
unit: "%"
}
},
comfortMode: {
description: "Behavior when the driver tips the indicator stalk.",
enum: {
literals: [
"OFF",
"THREE_FLASHES",
"FIVE_FLASHES"
],
default: "THREE_FLASHES"
}
}
}
}
Reading this from the outside in:
-
indicatoris a property name, called a relation. Property names are lowerCamelCase and become the keys the configuration author writes. -
entitymakes the element an entity: a named, referencable object that aggregates children. The children (flashFrequency,dimmingLevel,comfortMode) are parameters. -
multiplicity: "1..1"makes the element required exactly once. The default, when omitted, is"0..1"(optional).dimmingLevelandcomfortModeare therefore optional. -
Each parameter declares a scalar type (
u8,enum) with its constraints. Thedefaultis what applies when the configuration omits the value. -
titleanddescriptionare shown in hover and completion. Descriptions support Markdown. Write them, they are your API documentation.
Step 2: Validate the Definition
cfu def validate .
cfu discovers all definition files under the current directory and reports errors and warnings with file, line, and column.
A clean run prints nothing of concern and exits zero.
Try breaking the file (for example rename flashFrequency to FlashFrequency) to see a diagnostic.
Step 3: Write a Configuration
Create TurnIndicator.cfg.json5 next to it:
{
$definition: "TurnIndicator@1.0",
indicator: {
name: "FrontLeft",
flashFrequency: 2,
comfortMode: "THREE_FLASHES",
// dimmingLevel is omitted: the default 100 from the definition applies
}
}
-
$definitionbinds the file to your definition by name, and the version after the@states which definition version the configuration was written against, so version drift is detectable. Without it the file cannot be validated. -
namegives the entity its identity. Entities can carry anameand/or a globally uniqueid; the identity is used for references and, in mergeable modes, to merge the same entity across files. -
flashFrequencyis required (1..1), so leaving it out is an error.dimmingLevelis omitted and gets its default of 100.
Step 4: Validate the Configuration
cfu cfg validate .
This validates the configuration against the definition: required elements, value ranges, enum literals, patterns, references.
Set flashFrequency to 9 and run it again; you get an error pointing at the offending value, because the definition allows at most 3.
For continuous feedback during development add -t (continuous mode), which re-validates whenever a file changes:
cfu cfg validate -t .
Step 5: Look at What You Built
Two commands show the definition and the configuration the way the rest of the tooling sees them:
cfu def inspect . # the resolved definition as a tree: types, multiplicities, ranges, defaults
cfu cfg inspect . # the merged configuration
That is the whole loop: edit the definition, cfu def validate, write or adapt a configuration, cfu cfg validate, inspect the result.
Everything else in this manual adds features inside that loop.
Where to Go from Here
-
The definition system explains the model behind what you just wrote: documents, workspaces, type paths, and the validation flow.
-
Type reference covers every element type with examples.
-
Multi-file configurations shows how definitions allow their configurations to be split and merged across files.
-
Constraints add checks validating several values, such as a parameter required only in one mode.
-
Feature Interactions covers how features interact with each other.
-
Do and do not is the checklist to run over a definition before publishing it.
-
Code generation turns the definition into Rust and Python types your software consumes.
-
The user manual is worth a read of its own: it is what the authors of configurations against your definition see.