Native Swift App with Embedded Moltis Rust Core (POC)
This guide shows a proof-of-concept path to build a native Swift app where Swift is the UI layer and Moltis Rust code is embedded as a local library.
Goal:
- Keep business/runtime logic in Rust.
- Build native iOS/macOS UI in Swift/SwiftUI.
- Ship as one app bundle from the Swift side (no separate Rust service process).
Feasibility
Yes — this architecture is feasible with an FFI boundary.
The most practical POC shape is:
- Add a small Rust crate that compiles as
staticlib. - Expose a narrow C ABI (
extern "C") surface. - Call that ABI from Swift via a bridging header/module map.
- Keep Swift responsible for presentation and user interaction.
Recommended POC Architecture
SwiftUI / UIKit / AppKit
|
v
Swift wrapper types (safe Swift API)
|
v
C ABI bridge (headers + extern "C")
|
v
Rust core facade (thin FFI-safe layer)
|
v
Existing Moltis crates (chat/providers/config/etc.)
Boundary Rules
For the POC, keep the ABI intentionally small:
moltis_version()moltis_chat_json(request_json)moltis_free_string(ptr)moltis_shutdown()
Pass JSON strings across FFI to avoid unstable struct layouts early on.
Rust-side Implementation Notes
Create a dedicated bridge crate (example name: crates/swift-bridge):
crate-type = ["staticlib"]for Apple targets.- Keep all
extern "C"functions in one module. - Never expose internal Rust structs directly.
- Return
*mut c_charand provide explicit free functions. - Convert internal errors into structured JSON error payloads.
Safety checklist:
- Validate all incoming pointers and UTF-8.
- Do not panic across FFI boundaries (
catch_unwindat boundary). - Keep ownership explicit (allocator symmetry for returned memory).
- Do not leak secrets into logs or debug output.
Swift-side Integration Notes
Use YAML-generated Xcode projects for the POC (no hand-maintained .xcodeproj):
- Define app targets in
apps/macos/project.yml. - Generate project with XcodeGen.
- Link
Generated/libmoltis_bridge.aand includeGenerated/moltis_bridge.h. - Use a Swift facade (
MoltisClient) to own pointer and lifetime rules. - Keep Swift linted via
apps/macos/.swiftlint.yml.
From repo root:
just swift-build-rust
just swift-generate
just swift-lint
just swift-build
The UI remains purely SwiftUI while core requests/responses flow through the Rust bridge.
Intel + Apple Silicon (Universal libmoltis)
Yes — you can build libmoltis for both Intel and Apple Silicon and merge them into one universal macOS static library.
Build both architectures
rustup target add x86_64-apple-darwin aarch64-apple-darwin
# Intel
cargo build -p moltis-swift-bridge --release --target x86_64-apple-darwin
# Apple Silicon
cargo build -p moltis-swift-bridge --release --target aarch64-apple-darwin
Merge into one universal archive
mkdir -p target/universal-macos/release
lipo -create \
target/x86_64-apple-darwin/release/libmoltis_bridge.a \
target/aarch64-apple-darwin/release/libmoltis_bridge.a \
-output target/universal-macos/release/libmoltis_bridge.a
lipo -info target/universal-macos/release/libmoltis_bridge.a
This universal libmoltis_bridge.a can then be linked by your Swift macOS app, so one app build supports both Intel and M-series Macs.
Recommended packaging for Xcode
For production, prefer an XCFramework (device/simulator/platform-safe packaging) rather than manually juggling multiple .a files.
Async/Streaming Strategy
Moltis is async-first. For a POC:
- Start with request/response calls over FFI.
- Add streaming in phase 2 using callback registration or poll handles.
Simple incremental plan:
- Blocking/synchronous POC call (prove bridge correctness).
- Background
Taskwrapping on Swift side. - Token streaming callback API when stable.
Single-Binary Expectation Clarification
On Apple platforms, you typically ship a single app artifact that includes Swift executable + statically linked Rust library in one app bundle.
So for your POC requirement (Swift UI app that embeds Rust core without a separate Rust daemon), this is achievable.
POC Milestones
- Add
swift-bridgecrate exposing one health function (moltis_version). - Add one end-to-end chat method (
moltis_chat_json). - Build and link from minimal SwiftUI app.
- Validate memory lifecycle with repeated calls.
- Expand API surface only after the boundary is stable.
Risks to Watch Early
- ABI drift (solve with one owned header and narrow API).
- Threading assumptions across Swift and Rust runtimes.
- Logging and secret handling at the boundary.
- Cross-target build complexity (simulator vs device architectures).
Why This Fits Moltis
Moltis already has clear crate boundaries and async services. A thin FFI facade lets Swift own the native UX while reusing provider orchestration, config, and session logic from Rust.