types

Where components are usually declared, in *.components.ts, *.components.rs or *.components.py files. A component file can sit anywhere in the cognet — beside the systems that use it works just as well. types/ is the convention for keeping them together. See Components for what a component is.

types/
├── body/
│   ├── body.components.rs     # body/pose, body/velocity
│   └── imu/
│       └── imu.components.ts  # body/imu/sample
└── follow/
    └── follow.components.py   # follow/people, follow/target

Languages mix freely, file by file. Each file is read, never run.

Names come from the path

A component is named by its folder — less a leading types/ or src/ — and its type: Pose in types/body/ or src/body/ is body/pose. Moving a file renames everything in it. The same name declared twice — in any languages — fails at axonl prepare.

Exported means component

In each file, exported types are components. Everything else is a shape the components use, and has no name of its own in the world.

LanguageA componentA shape
TypeScriptexport interface / export typewithout export
Rustpub structwithout pub
Pythona top-level classa class whose name starts with _

export.components.* is what a folder offers

By convention, a folder's export.components.* holds what the rest of the mind is meant to read; its other component files are its working state. Nothing enforces it — any system may declare any component — but axonl debug graph shows every read across folders.

A lock beside the source

axonl prepare writes components.lock.json at the cognet's root: the number each field crosses as, kept when fields are reordered and reserved when they are removed. Commit it, as you would Cargo.lock — it is what keeps a recorded session readable after the types change.

Comments are documentation

The comment on a component shows in the editor, the debugger and Fleet. Write it for whoever sees the value at 0.62 and wonders why.