| name | logos-module-development |
| description | Activate when creating, building, testing, or modifying Logos modules — C++ Qt plugins, metadata.json config, CMake builds, LogosAPI usage, inter-module communication, code generation, packaging (LGX), or working with logos-cpp-sdk, logos-liblogos, logos-module, logos-module-builder repos. |
Logos Module Development
Read the full developer guide before making module changes:
repos/logos-tutorial/logos-developer-guide.md
This 1100-line guide covers the complete lifecycle. Key sections below.
Architecture
Modules are Qt 6 plugins (C++17) loaded by logoscore (headless) or logos-basecamp (GUI). Each module runs in its own host process (logos_host), communicating via Qt Remote Objects IPC.
logos-basecamp / logoscore -> logos_host (per module) -> module plugin (.so/.dylib)
|
Qt Remote Objects (IPC)
|
logos-cpp-sdk (LogosAPI, types)
Creating a module
mkdir logos-my-module && cd logos-my-module
nix flake init -t github:logos-co/logos-module-builder
nix flake init -t github:logos-co/logos-module-builder#with-external-lib
Generated structure:
flake.nix # ~15 lines, uses mkLogosModule
metadata.json # name, version, type, deps, cmake config (single source of truth)
CMakeLists.txt # ~25 lines
src/
my_module_interface.h # Q_INVOKABLE methods = public API
my_module_plugin.h/cpp # Implementation
metadata.json reference
{
"name": "my_module",
"version": "1.0.0",
"type": "core",
"category": "general",
"description": "Description",
"main": "my_module_plugin",
"dependencies": [],
"nix": {
"packages": {
"build": [],
"runtime": []
},
"external_libraries": [],
"cmake": {
"find_packages": [],
"extra_sources": [],
"extra_include_dirs": [],
"extra_link_libraries": []
}
}
}
Dependency names must match the name field in the dependency module's own metadata.json. Flake input attribute names must also match — e.g., waku_module.url = "github:logos-co/logos-waku-module".
Building and testing
ws build logos-my-module
ws test logos-my-module
ws build logos-my-module --auto-local
nix build
nix build .#lib
nix flake check
nix develop
cmake -B build -GNinja && cmake --build build
Inter-module communication (LogosAPI)
Modules call each other via LogosAPI:
#include <LogosAPI.h>
LogosAPI* api = LogosAPI::instance();
LogosResult result = api->callModule("other_module", "methodName", args);
if (result.success()) {
QVariant data = result.data();
}
Code generator
Auto-generate type-safe wrappers from a module's metadata:
logos-cpp-generator <plugin-file> [--output-dir <dir>]
logos-cpp-generator --metadata metadata.json --module-dir <dir>
Generates <ModuleName>Client.h with typed methods instead of raw string calls.
LogosResult
All cross-module calls return LogosResult:
result.success() / result.error() — check outcome
result.data() — return value (QVariant)
result.errorMessage() — error description
CLI tools
All tools are available directly (or as ws <tool>) and auto-build/rebuild from the local repo.
lm metadata <plugin-file> [--json]
lm methods <plugin-file> [--json]
logoscore -m <modules-dir> --load-modules <name> [-c "<module>.<method>(args)"]
lgx create <output.lgx> --name <name>
lgx add-variant <pkg.lgx> --variant <name> --files <path>
lgx list <pkg.lgx>
lgx verify <pkg.lgx>
lgpm install --file <path.lgx>
lgpm install --dir <dir-of-lgx-files>
lgpm list
lgpm info <package>
lgpd search <query>
lgpd list [--category <cat>]
lgpd categories
lgpd download <package> [-o <output-dir>]
logos-cpp-generator <plugin-file> [--output-dir <dir>]
logos-cpp-generator --metadata <metadata.json> --module-dir <dir>
Module types
- core — background services, no UI (loaded by logoscore or logos-basecamp)
- ui — Qt Widgets or QML-based UI (loaded only by logos-basecamp, displayed in tabbed workspace)
UI modules need "type": "ui" in metadata.json and must implement QWidget* createWidget() or provide QML.
Packaging for distribution
Manual packaging with lgx:
lgx create my_module.lgx --name my_module
lgx add-variant my_module.lgx --variant linux-x86_64 --files ./result/lib/my_module_plugin.so
lgx add-variant my_module.lgx --variant darwin-arm64 --files ./result/lib/my_module_plugin.dylib
lgpm install --file my_module.lgx
Automated Nix-based packaging uses nix-bundle-lgx (which uses nix-bundle-dir underneath):
nix-bundle-dir — bundles Nix derivations into portable self-contained directories (rewrites rpaths, resolves dependencies)
nix-bundle-lgx — wraps the bundled output into .lgx packages with platform variants and metadata
- Bundlers:
default (requires Nix store at runtime) or portable (fully self-contained)
Common pitfalls
- LogosAPI is only available when loaded by logoscore/logos-basecamp, NOT in module-viewer or standalone
- Module binary name must match
name in metadata.json (e.g., my_module -> my_module_plugin.so)
metadata.json must be alongside the binary for discovery
- Always build inside nix (raw cmake won't find Qt/deps)
- After adding
checks to a repo's flake.nix, run ws sync-graph