Universal modules build as header-first cdylibs now, but the docs still
described the old `logos-cpp-generator --from-header --backend qt` path that
emitted `<name>_qt_glue.h` + `<name>_dispatch.cpp` and listed them explicitly
in CMakeLists SOURCES. None of that is current:
- The generator derives a `.lidl` from the impl header, then runs the cdylib
backend → `<name>_cdylib_glue.{h,cpp}` (uniform Qt-plugin glue) +
`<name>_module_impl.cpp` (Qt-free C-ABI export wrapper).
- `mkLogosModule` runs the pipeline automatically — no `preConfigure`.
- `LogosModule.cmake` globs `generated_code/` — modules must NOT list the
generated files in SOURCES (the bug fixed in #12).
Updated across the board:
- guidelines/{codegen.md (rewritten),universal-module,nix-build,metadata-json}
- docs/{spec.md,project.md}, README.md
- skills/{create-universal-module,nix-flake-setup,wrap-external-lib}
- generators/generate-agents-md.ts, mcp-server/tools/build-help.ts
(build-help now flags the "generated_code in SOURCES" mistake directly)
- regenerated llms-full.txt + llms.txt
- refreshed the committed example trees (outputs/logos-*) to match current
`init` output: minimal flake (no preConfigure), CMakeLists without the
generated_code sources, and regenerated AGENTS.md/CLAUDE.md/.claude skills
- re-rendered dev-boost-scaffold-module.md
No source-code/behavior changes — docs + generated context only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.4 KiB
metadata.json Schema
Full Schema
{
"name": "my_module",
"version": "1.0.0",
"description": "What this module does",
"author": "Author Name",
"type": "core",
"interface": "universal",
"category": "general",
"main": "my_module_plugin",
"dependencies": [],
"include": [],
"capabilities": [],
"nix": {
"packages": {
"build": [],
"runtime": []
},
"external_libraries": [],
"cmake": {
"find_packages": [],
"extra_sources": [],
"extra_include_dirs": [],
"extra_link_libraries": []
}
}
}
Required Fields
| Field | Type | Description |
|---|---|---|
name |
string | Module identifier. Must match binary prefix: my_module -> my_module_plugin.so |
version |
string | Semantic version ("1.0.0") |
type |
string | "core" for modules, "ui_qml" for UI apps |
main |
string | Plugin binary name without extension: "my_module_plugin" (optional for pure QML UI apps) |
Universal Module Fields
| Field | Value | Description |
|---|---|---|
interface |
"universal" |
Signals that this module uses pure C++ impl + code generation |
When "interface": "universal" is set, mkLogosModule automatically runs the universal codegen pipeline (header → .lidl → cdylib glue) before CMake — no preConfigure needed. See codegen.md.
Dependencies
"dependencies": ["storage_module", "crypto_module"]
Values must match the name field in the dependency module's own metadata.json. The runtime loads dependencies before the module.
Flake input attribute names should also match the dependency module names when possible. Example: if you depend on storage_module from repo logos-storage-module, the flake input should be named logos-storage-module.
External Libraries
"nix": {
"external_libraries": [
{
"name": "mylib",
"build_command": "make static-library",
"output_pattern": "build/libmylib.*"
}
]
}
For Go libraries, add "go_build": true. The external library source is provided as a non-flake input in flake.nix and mapped via externalLibInputs.
Nix Packages
"nix": {
"packages": {
"build": ["pkg-config"],
"runtime": ["nlohmann_json", "openssl"]
}
}
build packages are available during compilation only. runtime packages are linked and available at runtime.
CMake Configuration
"nix": {
"cmake": {
"find_packages": ["Threads", "OpenSSL"],
"extra_sources": ["src/helper.cpp"],
"extra_include_dirs": ["include"],
"extra_link_libraries": ["Threads::Threads"]
}
}
These values are passed to CMake by the logos_module() macro. They supplement, not replace, the automatic SDK and Qt dependencies.
UI App Specific Fields
{
"type": "ui_qml",
"view": "Main.qml",
"icon": "icon.png",
"category": "tools"
}
| Field | Type | Description |
|---|---|---|
view |
string | Required for ui_qml. Path to QML entry point (e.g., "Main.qml" or "qml/Main.qml") |
main |
string | Optional. If present, indicates a C++ backend plugin (e.g., "my_app_plugin"). If absent, the app is pure QML |
Pure QML apps have no "main" field — no C++ compilation occurs. QML + backend apps have both "main" (C++ plugin) and "view" (QML entry point).
UI apps do not use "interface": "universal" — they use mkLogosQmlModule in their flake.nix.