Dario Gabriel LipicarandClaude Opus 5 4ba7aa1657 feat(shared-runtime): link the shared libraries, and delete the shim
PR-5 of the shared-runtime migration, logoscore-cli half. Both front-ends stop
emptying static archives and taking the runtime from liblogos_core, and link the
shared libraries that OWN those types instead.

DELETED: cmake/LogosSharedFromDll.cmake, its call, and LOGOS_SHARED_USE_DLL. The
shim made ld unable to pull an archive member that would redefine an imported
symbol; there is no second static copy left to suppress. The dllimport opt-in is
gone for the same reason -- the import is what the link now produces.

Takes the pin SET, not one pin: logos-protocol 2e3344a (#65), logos-plugin-qt
1aa3e31 (#22), logos-liblogos b2a9a0b (#182). Bumping one alone gives a
combination where the shared targets do not exist or do not match.

THE GATE NEEDED THE SAME TWO CORRECTIONS AS BASECAMP'S, plus one this repo
surfaced on its own. All three were the check measuring the wrong thing.

  * It hardcoded liblogos_core as THE provider. True while liblogos_core
    absorbed both archives; false now. Replaced with EXACTLY-ONE-DEFINER per
    type, which is provider-agnostic and survives ownership moving again.
  * The negative control planted a copy of liblogos_core as its "duplicate
    runtime". liblogos_core defines ZERO runtime symbols now, so it planted
    nothing and the control correctly reported itself vacuous. It plants a real
    DEFINER instead.
  * NEW HERE: this gate listed every lib/*.dylib as a CONSUMER, so it scanned
    the owners under "no consumer defines the runtime" and reported

        liblogos_protocol.dylib   35   SPLIT-BRAIN

    which is simply the library doing its job. Owners are now separated from
    consumers: counted in the exactly-one assertion, excluded from the
    nothing-else-defines-it scan. basecamp's gate never hit this because its
    consumer set is the exe plus plugins/, not lib/.

StoreRegistry stays out of the exactly-one list: token_manager.cpp defines
`static StoreRegistry r;` inside registry(), so it has a LOCAL symbol and no
external one. Requiring one definer of something never exported would fail
forever. It remains in the TIER 1 scan, where "no consumer defines it" is
meaningful precisely because it should never become external.

VERIFIED, aarch64-darwin:

  .#default                      PASS
  checks.tests                   PASS
  checks.symbol-gate             PASS
  checks.symbol-gate-negative    PASS

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 11:45:55 -03:00

logos-logoscore-cli

The headless CLI runtime for the Logos modular application platform. It loads Logos modules — Qt plugins and Qt-free universal / cdylib ones alike — and lets you call their methods from the command line, no GUI needed.

This repo is one of two frontends for logos-liblogos:

  • logos-logoscore-cli (this repo) — headless CLI runtime for scripting, testing, and headless deployments
  • logos-basecamp — the desktop GUI application shell

Two binaries

Documentation
logoscore The tool that exists today. Commands, flags, config format and ~/.logoscore are unchanged. Keep using it. docs/logoscore.md
logosctl logoscore + lgpd + lgpm merged into one, with package management built in. New surface, own ~/.logosctl session directory. Being validated; not yet the default. docs/logosctl.md

They share the runtime but no state, so a logosctl session cannot disturb a logoscore deployment. They are built from separate flake outputs and released as separate artifacts. logoscore will be removed only once logosctl has been properly validated in real use.

Everything below applies to both. For what each tool actually does — commands, configuration, authentication, transports — follow the links above.

How to Build

The two binaries have separate flake outputs. cli is logoscore, ctl is logosctl, and each ships only its own binary — so nix build with no target, and anything already pointing at .#cli, still gets logoscore exactly as before.

Output Binary
.#cli (default) logoscore dev build
.#cli-bundle-dir logoscore portable, self-contained directory
.#cli-appimage logoscore portable, single-file AppImage (Linux)
.#ctl logosctl dev build
.#ctl-bundle-dir logosctl portable, self-contained directory
.#ctl-appimage logosctl portable, single-file AppImage (Linux)

Both come in two flavors: a dev build for local iteration and a portable build for distribution. The dev build links against dev logos-liblogos and works with dev modules; the portable build is self-contained and works with portable modules — which is what the public catalog ships, so installing from the catalog needs the portable bundle. Installing a locally built .lgx is the mirror image: a nix module build produces a -dev variant, so the dev build is the one that takes it. See installing a local .lgx.

Dev Build

A standard Nix derivation whose dependencies live in /nix/store. It is the fastest way to iterate during development but is not portable — it only runs on the machine that built it. It works with dev modules: those produced by a local module nix build, or installed by the package manager's dev build.

nix build                        # logoscore (dev) — same as '.#cli'
nix build '.#ctl'                # logosctl (dev)
./result/bin/logoscore --help

Portable Builds

Portable builds are fully self-contained — no /nix/store references at runtime. They work with portable modules: releases from logos-modules, or modules installed by the package manager's portable build.

Output Platform Format
cli-bundle-dir / ctl-bundle-dir Linux, macOS Self-contained flat directory with bin/, lib/, and modules/
cli-appimage / ctl-appimage Linux Single-file .AppImage executable
Self-contained directory bundle (all platforms)
nix build '.#cli-bundle-dir'
./result/bin/logoscore --help
Linux AppImage (Linux only)
nix build '.#ctl-appimage'
./result/logosctl.AppImage --help

Development Shell

nix develop

Note: In zsh, quote targets containing # to prevent glob expansion (e.g., '.#cli').

If you don't have flakes enabled globally:

nix build --extra-experimental-features 'nix-command flakes'

Running Tests

Each binary has its own suite, in its own derivation, so nix builds them concurrently. tests runs both.

Check Covers
.#checks.<system>.tests both — this is what CI runs
.#checks.<system>.tests-logosctl unit + CLI + integration for logosctl
.#checks.<system>.tests-logoscore CLI + integration for logoscore

The logoscore suite is a deliberate duplicate of the logosctl one, frozen against logoscore's surface. It exists so that changes to the shared runtime cannot regress the tool people are actually using, and it gets deleted along with the binary.

# Both suites
nix build '.#checks.aarch64-darwin.tests'

# One suite, and its binaries, for local iteration
nix build '.#tests'
./result/bin/cli_tests
./result/bin/cli_tests --gtest_filter=CLITest.*

# Or via nix checks
nix flake check

Dependency Resolution

When loading modules, both binaries automatically resolve and load transitive dependencies in the correct order. For example, if logos_irc depends on waku_module and chat, loading logos_irc alone is equivalent to loading waku_module,chat,logos_irc.

Supported Platforms

  • macOS (aarch64-darwin, x86_64-darwin)
  • Linux (aarch64-linux, x86_64-linux)
S
Description
No description provided
Readme
16 MiB
Languages
C++ 89.6%
Nix 6.5%
CMake 1.9%
Shell 1.8%
Groovy 0.2%