Early project. Marfa is at version 0.0.x. Things will change without notice, and nothing is stable yet.
The Swift SDK for Marfa, a home for your personal data that you run yourself. It is the Swift package Marfa, and it lets an iOS or macOS app work with a Marfa instance.
An app built on it keeps a working copy of the data it needs on the device. The app reads from that copy with or without a connection, queues its writes until it can send them, and follows changes from the instance. The package gives you Swift types, async calls, change streams and typed errors over Marfa's Rust core, which does the networking, storage and syncing.
- iOS 27 or macOS 27
- Xcode 27 or later, with Swift 6.4, on a Mac with Apple silicon
The core is built for Apple silicon only. In your app target's build settings, set Excluded Architectures for Any iOS Simulator SDK to x86_64, or some simulator builds fail to link.
In Xcode, choose File > Add Package Dependencies, enter https://github.com/withmarfa/marfa-swift, and add the Marfa product to your app's target. Use the version of the latest release.
In a Package.swift, add the package and the product:
.package(url: "https://github.com/withmarfa/marfa-swift", exact: "<latest release>"),.product(name: "Marfa", package: "marfa-swift"),Each release includes the core prebuilt, so your app needs no Rust toolchain.
This opens a working copy, fills it with the notes on your instance, and prints their titles. You need a running instance and a key that can read core.note; the Quickstart makes both.
import Marfa
let server = Server(url: serverURL, key: key)
let copy = try await WorkingCopy.open(store: storeURL, server: server)
_ = try await copy.hydrate(types: ["core.note"], tier: .library)
for note in try await copy.items.list(ListFilters(type: "core.note")) {
print(note.title ?? "Untitled")
}storeURL is where the working copy keeps its SQLite file, and serverURL is your instance's address. Keep key in the keychain between launches with Keychain.system; the copy holds it in memory and never writes it to its store.
The MarfaTesting product provides a working copy for tests and SwiftUI previews, without a store, a server, or a call into the Rust core. Add it to test targets. Its module compiles empty in a release build, so nothing from it ships; wrap its uses in #if DEBUG. Pass fake.copy wherever a view model accepts a WorkingCopy:
#if DEBUG
import MarfaTesting
#Preview {
let fake = WorkingCopy.fake(items: [note], itemTypes: [noteType])
NotesView(model: NotesModel(copy: fake.copy))
}
#endifUse FakeCopy to record writes, choose drain verdicts, and send changes on changes(). Unsupported calls throw FakeCopyError.unsupported. The FakeCopy API documentation lists the supported calls.
The documentation is at docs.marfa.so.
- Swift SDK: the working copy, items, queued writes, change streams, live queries, conflicted copies and folders on a Mac.
- Build an app with Swift: a tutorial that builds a SwiftUI app for iPhone and Mac.
- Devices: how an app keeps a working copy and sends its changes.
- Write safely: versions, conflicts and retries.
- Sync a folder: keep a directory on your Mac in step with your notes.
- API reference: the HTTP API the SDK is built on.
The server, the core and the contract are in withmarfa/marfa.
To work on the package itself, build its pinned core first, which needs the Rust toolchain and Node.js 22 or later:
scripts/core.sh
swift build
swift testExamples/MarfaSample is a SwiftUI sample app; run xcodegen generate in that folder to make its project. AGENTS.md holds the rules for working in this repository.