Library / SDK
opral/lix avatar
opral/lix

opral/lix: a versioned repository you embed in your own product

Embeddable repository that combines files, database, and version control.

754 stars24 forksRustMIT

At a glance

What is it?
Lix puts files, a SQL database and version control into one embeddable repository, exposed through a TypeScript SDK and a Rust core under the MIT licence. It is aimed at products that need per-customer history, diffs and rollback without building those features themselves, and it is still pre-1.0.
Who is it for?
Adopt lix if you are building a product that must give each customer their own history, diffs and rollback, and you are willing to track a pre-1.0 API that moved through three releases in a single week. Do not adopt it if you need per-file permissions today, since the README lists those as coming, or if you require a stable Rust or Python SDK, because the quickstarts cover JavaScript and Rust and the Python and Go SDKs are still open issues.
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 1 day ago.
What is it written in?
Mainly Rust, 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 gap lix fills: history as a query, not a feature you build

Most products end up with a database that stores current state and a separate audit table that stores who changed what. The audit table is written by hand, it drifts from the real schema, and it cannot describe a file. Lix takes the opposite position: the repository itself is the source of truth, and every write is recorded with its author. The README describes it as "Files, SQL database, and version control in one" and states that "Everything inside is versioned data: file content, app tables, reviews, comments." That is the claim to evaluate.

The intended audience is product teams rather than individual developers. The README's first use case is giving every customer their own repository, with the note that "Non-technical users get accept and undo, not branches and pull requests." The second is syncing the files that coding agents work on. The third is apps that want history, blame, branching and rollback without building them. All three assume you are shipping software to other people and want to hand them version control as a feature.

How files become versionable rows

The mechanism is plugins. According to the README, "Plugins make supported formats queryable as versioned rows," and the diagram caption describes a plugin mapping /orders.csv to SQL rows with row, field and value columns. A paragraph, a cell or a property becomes a row that Lix can version. That is why diffs can name "the clause, cell, or row that changed, not a byte blob."

This is the design decision everything else rests on. If you store a CSV as an opaque blob, a diff is a byte comparison and a merge is a conflict. If you store it as rows, a diff is a set of row-level changes and the merge has something to reason about. The cost is that someone has to write and maintain a plugin per format, and the README does not enumerate which formats ship today. That is the first thing to check in the repository before you plan around it.

Files and rows share one transaction. The README states that "Files and rows update in one ACID transaction," which is what makes the combined rollback claim meaningful rather than aspirational.

Storage options and the server boundary

Lix runs in-process. The README says it "runs in-process with pluggable storage: in memory, on the local filesystem, or in a server backed by S3," and lists local filesystem, SQLite on browser OPFS, and S3 behind a Lix server as the pluggable options. The homepage is lix.dev, and hosting documentation lives at docs/hosting.md in the repository.

The practical consequence is that there is no external control plane to sync. Nothing sits between your process and the data except the storage backend you choose. When you point openLix at a server URL, the server is the storage layer, not a coordination service. The README's file-sync example keeps ./project as a normal directory on disk while syncing it through a server, which means the files remain usable by ordinary tools even while Lix tracks them.

Getting a repository open: the two entry points

The published package is @lix-js/sdk, installed alongside a storage package. The README gives this command: npm install @lix-js/sdk @lix-js/storage-filesystem. You then call openLix with a storage instance, and the example passes new FilesystemStorage({ path: "./repository" }).

Writes go through ordinary SQL. The README inserts a file with:

await lix.execute("INSERT INTO lix_file (path, content) VALUES ($1, $2)", ["/notes/status.txt", new TextEncoder().encode("ready")]);

The alternative entry point is remote. You pass server: { url: "https://example.com/repositories/acme" } instead of a storage object, and the README's per-customer example builds that URL from a customer id. Reading history is also SQL. To populate a history sidebar the README queries created_at, account_id, schema_key, row_pk and snapshot_content from lix_change, ordered by created_at descending. Those two table names, lix_file and lix_change, are the concrete surface you should confirm against your own data before designing a UI around them.

Where the documentation is thin, and what that costs you

Permissions are not implemented. The README labels them "(soon)" and says they "will live inside the repository: per file, per group, and versioned like any other change." Until then, the finance, legal and contractor access split described in that bullet does not exist inside Lix. If your product needs per-file access control today, you enforce it in your own layer, and a repository handed to a customer is all-or-nothing.

The SDK surface is uneven. The getting-started row offers JavaScript and Rust quickstarts, then links Python and Go to GitHub issues with the note that they are planned. The repository's primary language is Rust, so the core is there, but an application team working in Python has no supported path in the material provided.

The plugin catalogue is unspecified. The README asserts that plugins make formats queryable and shows CSV as the illustration, but it does not list which formats are covered. A format without a plugin is still storable as a file, it just will not diff at the row level, which weakens the main selling point for that format.

Finally, the release cadence is worth reading as a signal about stability rather than popularity. The three most recent releases are v0.15.0 on 7 September 2026, v0.15.1 the same day, and v0.16.0 on 9 September 2026. Two minor versions and a patch inside three days, all below 1.0. Plan for API movement between upgrades.

The alternative to weigh: Git plus a database

The obvious comparison is a Git repository for the files and a separate relational database for the application data, with your own code keeping the two in step. That approach is mature, the tooling is everywhere, and every engineer already understands branching and merging.

The difference is where the history lives and what it can describe. Git versions files and knows nothing about your orders table; a database versions rows and knows nothing about your files. Reconciling them means a commit that touches both can fail halfway, because the two systems do not share a transaction. Lix's claim is that files and rows update in one ACID transaction and that diffs name the clause, cell or row rather than a byte blob. If your product needs a single undo that covers a document edit and a status change together, that is the gap Git plus a database leaves open. If your files are already text and your users are engineers, Git is the cheaper answer and Lix adds a dependency you do not need.

Licence, maintenance and what to check before adopting

The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is permissive and imposes no copyleft obligation on your product. It is not legal advice; read the LICENSE file in the repository and confirm it matches what your organisation requires.

Maintenance cost is the part the README cannot tell you. The project is not archived and the last push recorded is 10 September 2026, one day after v0.16.0. That is active, but active at a pre-1.0 stage. The upgrade cost is real: v0.15.0, v0.15.1 and v0.16.0 all landed within the same week, so a pinned version will fall behind quickly and an unpinned one will surprise you. Budget for reading release notes before each bump.

There is also an operational decision embedded in the storage choice. FilesystemStorage keeps files on disk where other tools can read them, which makes migration away from Lix possible. A server backed by S3 centralises the data and makes the server a component you now run and monitor. The README points at docs/hosting.md and at LixRay for a hosted option, so the self-hosted path exists but its operational detail is outside the material summarised here.

Editorial conclusion

Adopt lix if you are building a product that must give each customer their own history, diffs and rollback, and you are willing to track a pre-1.0 API that moved through three releases in a single week. Do not adopt it if you need per-file permissions today, since the README lists those as coming, or if you require a stable Rust or Python SDK, because the quickstarts cover JavaScript and Rust and the Python and Go SDKs are still open issues. Before committing, verify the current on-disk format by opening a repository with FilesystemStorage, running the lix_change query from the README, and confirming that the rows you get back are the ones your UI needs to render.

Official sources

  1. License: MIT
  2. opral/lix on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes