Model or dataset
rryam/VecturaKit avatar
rryam/VecturaKit

VecturaKit: On-Device Vector Search in Swift, Minus the Server

Swift-based vector database for on-device RAG using MLTensor and MLX Embedders

320 stars30 forksSwiftMIT

At a glance

What is it?
VecturaKit is an MIT-licensed Swift package that keeps embeddings, indexing and hybrid search inside the app process, with pluggable embedders for NaturalLanguage, MLX and any OpenAI-compatible /v1/embeddings endpoint. The design is sound for Apple-platform apps that cannot ship a backend; the cost is a hard floor of iOS 18, macOS 15 and Swift 6.0, plus storage and memory behaviour you have to verify yourself.
Who is it for?
Adopt VecturaKit if you are shipping an Apple-platform app that must answer retrieval queries offline or without a server round trip, and your minimum targets are already iOS 18, macOS 15, tvOS 18, visionOS 2 or watchOS 11 on Swift 6.0. Do not adopt it if you need a queryable index that many processes or machines share, if you are constrained to older deployment targets, or if you want the embedding model and the store versioned as one artifact.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem: retrieval without a server in the loop

Most retrieval-augmented generation stacks assume a network hop. You embed a corpus somewhere, push vectors into a hosted store, and query it from the client. For an iOS or macOS app that has to work offline, that architecture fails at the first airplane-mode user, and it also means shipping document text off the device. VecturaKit takes the opposite position: the vector store lives in the app's own storage directory, the embedder is a protocol you supply, and search runs locally. The README frames this as "local vector storage and retrieval" for on-device apps, and the feature list backs it up with persistent storage, batch indexing and configurable search thresholds. The audience is narrow and clearly defined. This is for Swift developers building note apps, document assistants, offline search, or private RAG over a user's own files. It is not a service component, and nothing in the material suggests a server mode.

How the pieces fit: embedder protocol in, hybrid search out

The architecture has three swappable seams. VecturaEmbedder is the embedding contract; the README lists four concrete implementations: OpenAICompatibleEmbedder for any /v1/embeddings endpoint, NLContextualEmbedder wrapping Apple's NaturalLanguage framework, SwiftEmbedder from the separate VecturaEmbeddingsKit package, and MLXEmbedder from VecturaMLXKit. VecturaStorage is the persistence seam, with the README naming SQLite, Core Data and cloud storage as examples of what you could implement. VecturaSearchEngine is the ranking seam. The default search path is hybrid: vector similarity combined with BM25 text search, with weights exposed as configuration. Dimension detection is automatic, read off the configured embedder, which removes a common source of mismatch bugs when you swap models. Documents are indexed in parallel, and state is saved and reloaded across app sessions. The trade-off embedded in this design is that you own consistency: because storage and search are protocols, a custom VecturaStorage implementation can diverge from what the search engine expects, and the README does not describe a transaction or migration story for that case.

Getting it into a package: dependencies and minimum targets

Distribution is through Swift Package Manager. The README gives the dependency line as .package(url: "https://github.com/rryam/VecturaKit.git", from: "6.3.0"), and products are added per target: VecturaKit for the core database, VecturaOAIKit for OpenAI-compatible embeddings, VecturaNLKit for NaturalLanguage. MLX and swift-embeddings support are not in this package. They come from VecturaMLXKit, pinned at from: "3.0.2", and VecturaEmbeddingsKit, pinned at from: "1.1.0". That split matters for planning: a three-product app plus an embedder package is four moving version constraints, and the release cadence visible in the repository is roughly monthly (6.1.0 in April 2026, 6.2.0 in July, 6.3.0 in August), so the pins will drift. Platform floors are stated plainly: macOS 15.0, iOS 18.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, with Swift 6.0 or later. Those are not soft recommendations; the package declares them. The only dependency named in the truncated README is swift-argument-parser, which the CLI tools would need. The list may continue beyond the cut.

Two CLI tools and what they are actually for

The repository ships vectura-cli, described as a NaturalLanguage-backed tool for local workflows, and vectura-oai-cli, for exercising OpenAI-compatible embedding providers from a terminal. Read the README's wording carefully: these are for "trying" providers and for local workflows, not for production ingestion pipelines. If you need to load a large corpus once and inspect what the hybrid search returns before you wire it into an app, vectura-cli is the shortest path, because NLContextualEmbedder has zero external dependencies. vectura-oai-cli is the counterpart when your app will talk to a local server exposing /v1/embeddings. Both are thin surfaces over the same core, so anything you learn from them transfers to the library. What the material does not provide is a documented schema for the on-disk format, so treat the CLI as a probe rather than a migration tool.

The memory mode decision is the one that will bite

The feature list offers three memory management strategies: automatic, full-memory and indexed, positioned for datasets "ranging from thousands to millions of documents", with a pointer to Docs/INDEXED_STORAGE_GUIDE.md. This is the most consequential configuration choice in the project and the README does not summarise the trade-offs inline. Full-memory mode is the straightforward interpretation: vectors resident, fastest lookups, memory proportional to corpus size, which on a watch or a phone is a real ceiling. Indexed mode implies disk-backed lookup with some per-query cost. Automatic presumably picks based on size, but the README does not state the heuristic. Anyone planning a corpus beyond a few thousand documents should read that guide before writing the initialization code, because switching modes later touches the storage layer, not just a flag. This is a case where the documentation is thin at the top level and the answer lives one link deeper.

Where VecturaKit is the wrong tool

Three failure modes are visible from the material alone. First, multi-process access: nothing in the README describes locking, concurrent writers or a daemon, so if two extensions, a widget and the main app all want to write, you are designing that coordination yourself on top of VecturaStorage. Second, deployment targets. iOS 18 and macOS 15 are recent floors, and an app that still supports iOS 17 cannot use this at all, regardless of how well the API fits. Third, watchOS. The package declares watchOS 11 support, but the memory management section talks about datasets up to millions of documents, and a watch is not that device. Choosing indexed mode there is an untested assumption unless you verify it. There is also a subtler issue: because the embedder is pluggable and dimensions are auto-detected, changing embedder models after users have stored data is a migration problem the README does not address. Vector dimensions from NLContextualEmbedder and from an MLX model will not match, and re-embedding a user's corpus on device is expensive.

The alternative: a general-purpose embedded store

The obvious comparison is SQLite with a vector extension, or another embedded store such as LanceDB, rather than a hosted vector service. The difference in approach is real. SQLite gives you one file, a mature transaction model, a query language, and an ecosystem of tooling, at the cost of assembling embedding and ranking yourself and dealing with a C API from Swift. VecturaKit inverts that: it hands you a Swift-native hybrid search pipeline with BM25 and vector similarity already combined, and a protocol for the embedder, but it does not give you SQL, joins or a documented on-disk format you can inspect with standard tools. If your retrieval needs are simple and your team is Swift-only, the protocol-oriented API is less work. If you need to query the store from Python for evaluation, or you want transactional guarantees across multiple writers, SQLite is the safer base. The README also credits Dripfarm's SVDB as the inspiration, which is the closest prior art in the same language and worth reading for comparison.

Maintenance, licensing and what to pin

The licence is MIT, which permits commercial and closed-source use with the usual requirement to retain the copyright notice and permission text. That is a permissive baseline, and no legal advice is implied here; check the LICENSE file in the repository for the exact terms. Maintenance cost is mostly version pinning. The project released 6.1.0, 6.2.0 and 6.3.0 between April and August 2026, and the last push to the default branch was 2026-08-31, so the codebase is active. Two of the four embedders live in separate repositories with their own version lines, which means an upgrade to VecturaKit can require a matching bump in VecturaMLXKit or VecturaEmbeddingsKit. Use from: constraints as shown in the README rather than branch tracking, and re-run your retrieval evaluation after each bump, because hybrid search weights and thresholds are exposed configuration and defaults can shift between minor versions. The repository is not archived, so there is no abandonment signal, but there is also no stated support policy in the material provided.

Editorial conclusion

Adopt VecturaKit if you are shipping an Apple-platform app that must answer retrieval queries offline or without a server round trip, and your minimum targets are already iOS 18, macOS 15, tvOS 18, visionOS 2 or watchOS 11 on Swift 6.0. Do not adopt it if you need a queryable index that many processes or machines share, if you are constrained to older deployment targets, or if you want the embedding model and the store versioned as one artifact. Before writing code, decide which memory management mode you need by reading Docs/INDEXED_STORAGE_GUIDE.md, confirm your embedder choice does not pull in a second package you have not budgeted for, and pin the version rather than tracking main.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. rryam/VecturaKit on GitHub
Community notes

Community notes