Lumi
Extensions

Publishing

How an extension gets into the store — source in, signed package out.

The store keeps one promise: the reviewed source is the shipped package. You submit source, pinned to a commit; the store's own build compiles it, packages it, signs it and publishes it. No binary you built is ever published, so nothing can be swapped after review.

That is also why a package you build yourself installs as not signed: only the store's build signs, and Lumi says so rather than pretending otherwise. (A package downloaded from the store and installed from a file keeps its signature if its .sig file sits beside it, as <package>.sig.)

Submitting

Put the source in a public repository

A Rust crate depending on lumi-extension-api, with manifest.toml beside its Cargo.toml. Anything under ui/ is packed exactly as it is in the repository, so commit it as source — see Building for the store.

Open a pull request against the store

The store lives at github.com/thiennguyen93/lumi-store. The pull request:

  • adds your repository as a submodule under ext/<your-extension-id>, pinned to the exact commit you are submitting, and
  • adds one entry to extensions.toml:
[[extension]]
id = "dev.you.thing"       # must equal the id in your manifest.toml
path = "ext/dev.you.thing" # the submodule
subdir = "."               # where Cargo.toml and manifest.toml live inside it

Review

Review is by a person, of the source: the capabilities the manifest declares against what the code actually calls, nothing phoning home, and no misbehaviour shipped as a feature. The pull request's checks also hold the manifest to the rules Lumi's installer applies, so a manifest Lumi would refuse fails there rather than on somebody's Mac.

Merge

Merging is publishing: the store rebuilds every listed extension from source, signs the packages and rewrites the index Lumi reads.

How people find it

Store, in the row above the list in Settings → Extensions, opens the store's page on lumikeys.app in the browser. Its Install button hands the extension back to Lumi, which downloads the signed package and shows the same review sheet a file install gets — this time saying the package came from the store and was verified against its key. Nothing installs until the person presses the sheet's button — Install, or Continue… when the extension ships an installer of its own.

Updates

An update is a pull request that moves your submodule to a new commit and raises version in the manifest. The id never changes — it is how Lumi knows the new package replaces the old one.

Lumi reads the store's index at launch, when its window comes forward, and once an hour in the background, at most every six hours — and whenever the person presses Check for updates… in Settings → Extensions. An update is offered when the store's version is higher than the installed one, compared as numbers, so 1.10.0 is newer than 1.9.0. Both must be written major.minor.patch; a version of any other shape is never offered as an update. An update whose min-lumi-version is above the running Lumi is listed as needing a newer Lumi.

An update keeps the person's settings, and your installer is not shown again. If your extension is switched on, it is told with Updated, carrying the version it replaced.

Keep capabilities as narrow in an update as in the first release: a new capability is a new line on the review sheet.

On this page