binary
two platforms, one artefact
$ file ./eximia
./eximia: ELF 64-bit · also macos aarch64
$ ls -lh ./eximia
-rwxr-xr-x 2.1M ./eximia
v0.2.0 · standalone build engine
One binary. Drop in your app source. Get a signed APK or IPA back. Extend it with your own Kotlin and Swift plugins — called from your app like any typed JS module.
By the numbers
binary
two platforms, one artefact
$ file ./eximia
./eximia: ELF 64-bit · also macos aarch64
$ ls -lh ./eximia
-rwxr-xr-x 2.1M ./eximia
npm deps
no install dance
$ which node
node: command not found
$ ./eximia build --spec eximia.json
✓ works anyway
bridge
kotlin · swift · js, typed
class WiFiInfo : SLMEximiaPlugin { … }
// from JS, fully typed:
await SLMEximia.plugin('WiFiInfo').scan()
build
typical signed APK
$ time ./eximia build --release
✓ signed app.apk (135 MB)
real 0m45.123s
Cordova's 2010s API and npm-orchestrated install dance is the cost we stopped paying. Same WebView model, modern stack, single binary you own.
The 2010s way
Spend an afternoon installing nine npm packages, then pray the plugin merger doesn't overwrite your manifest.
The 2026 way
Download one binary, write one spec, run one command. Get a signed APK and IPA back.
How it works
Write a tiny eximia.json, drop your HTML/CSS/JS
app source next to it, run the binary. Watch the build happen
in real time.
$ cat eximia.json
{
"appId": "com.example.app",
"version": "1.0.0",
"platforms": ["android", "ios"],
"app": { "dir": "./www" },
"plugins": ["./plugins/wifi-info"]
}
$ eximia build --spec eximia.json --out ./build/
✓ resolved plugins from spec (1s)
✓ staged HTML/CSS/JS app from ./www (0s)
✓ compiled Android runtime (8s)
✓ assembled and signed app.apk (36s)
$ ls build/
app.apk app.ipa
$ _
Extend
Eximia ships with one working plugin — device-info —
as a complete reference. Everything else, you write. The bridge
does the marshalling; you focus on the platform code.
class WiFiInfo : SLMEximiaPlugin {
override suspend fun execute(
action: String,
args: JSONObject,
cb: SLMEximiaCallback,
) {
when (action) {
"scan" -> cb.success(scanWiFi())
else -> cb.unknownAction(action)
}
}
}
final class WiFiInfo: SLMEximiaPlugin {
func execute(
action: String,
args: [String: Any]
) async throws -> Any {
switch action {
case "scan": return try await scanWiFi()
default: throw SLMEximiaError.unknownAction
}
}
}
import { SLMEximia } from '@slm/eximia';
// Typed proxy generated from plugin.json.
const wifi = SLMEximia.plugin<WiFiInfo>('WiFiInfo');
const nets = await wifi.scan({ secured: true });
console.log(nets[0].ssid); // "MyNetwork"
A plugin is a directory with plugin.json, a Kotlin
source, a Swift source, and a JS entry. The CLI auto-injects
permissions, Gradle deps, Info.plist keys, and SwiftPM packages
declared in the manifest.
Get started
The installer detects your platform, fetches the matching
binary from slmeximia.site/downloads, verifies
the SHA-256, and drops eximia in ~/.local/bin.
Linux x86_64 and aarch64 ship today; macOS arm64 next.
$ curl -fsSL https://slmeximia.site/install.sh | sh
[eximia] host: linux/x86_64 → target=linux-x86_64
[eximia] version: v0.2.0
[eximia] downloading slm-eximia-v0.2.0-linux-x86_64
[eximia] sha256 verified
[eximia] installed → ~/.local/bin/eximia
$ eximia --version
slm-eximia 0.2.0
First public release shipping today. New here? Start with the 10-minute quickstart — install, init, build, first APK in one sitting. Need an internal plugin? See licensing.