xorq-labs/xorq: a git-native executable catalog for agentic data work
Git-native executable catalog for agentic data work.
At a glance
- What is it?
- Xorq turns Ibis dataframe expressions into content-addressed build directories that live in a Git catalog, so an agent or a human can run a pipeline instead of reading a note about it. The idea is sound; the documentation is still thin on operational details.
- Who is it for?
- Adopt Xorq if you already write Ibis expressions and want agent output to land as runnable, hash-addressed entries in a Git repo rather than a folder of one-off scripts. Skip it if your pipelines are plain pandas with no Ibis layer, or if you need a governed metadata catalog with owners and policies, since Xorq catalogs computation, not assets.
- Can I use it commercially?
- Yes. Apache-2.0 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 Python, 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 agent tech-debt problem Xorq is aimed at
Ask a coding agent for a dashboard and the README predicts what you get: a folder of one-off Python scripts that import each other in non-obvious ways, an embedded JSON blob holding intermediate state, and a requirements.txt regenerated two sessions ago. The result may run on the machine that produced it. Reproducing it elsewhere, or productionizing any part, means rewriting some of it.
The README frames the failure in four rows. Imperative, stateful artifacts mean reproducing a result requires re-running files in the right order because no declarative spec exists. There is no discoverable shared index: team memory today is markdown notes under a directory with an index of one-liners pointing at them, and no executable catalog two agents can both pull into context. There is no lineage graph, so renaming an upstream column breaks a downstream model at runtime because the dependency lived in chat history. And there is no portable environment, so a pipeline that ran in one agent session has no path to another sandbox or to production.
The intended user is a data or ML engineer working alongside agents, not a business analyst browsing a governed catalog. Xorq's answer is to make the computation itself the cataloged object, with a hash for identity and a pinned environment attached.
How a dataframe expression becomes a content-addressed entry
The mechanism rests on Ibis, which Xorq uses as its expression system. An expression is lazy: it describes the transformation without executing it. The README's penguins example filters rows, groups by species, and computes a mean bill length, and that structure is what Xorq hashes.
The build step packages two things together. One is the manifest, described as expr.yaml plus a metadata JSON file, which captures the computation including operations, schema, lineage, and inputs. The other is the environment: a wheel and a pinned requirements.txt. The output lands in a hashed directory such as builds/fa2122f6a9e9/, and that hash is the entry's identity.
Adding the build to a catalog makes it discoverable by hash or by a human-readable alias. The catalog itself is a Git repository of entries, with git-annex support for large files. Execution runs on DataFusion for embedded in-process SQL and UDF work, and operators exchange Arrow RecordBatches, which is also the IPC and network format. The same expression can target DataFusion, DuckDB, SQLite, pandas, Snowflake, Databricks, Trino, Postgres, PyIceberg, or GizmoSQL, and into_backend moves data between them. The lineage claim is the interesting one: because the dependency graph is captured at build time rather than reconstructed from chat history, a renamed column is a graph fact, not a runtime surprise.
Installing Xorq and building a first catalog entry
The README gives two entry points. The manual path installs the library with the examples extra, which is what pulls in the sample datasets:
pip install xorq[examples]
xorq init -t penguinsThe init command scaffolds a project against the penguins template. From there you write a lazy expression into expr.py. The README's example imports xorq.api as xo, fetches the penguins data, filters out null species, groups by species, and aggregates a mean bill length into a column named avg_bill_length:
import xorq.api as xo
penguins = xo.examples.penguins.fetch()
penguins_agg = (
penguins
.filter(xo._.species.notnull())
.group_by("species")
.agg(avg_bill_length=xo._.bill_length_mm.mean())
)Building that file produces the hashed directory. The command is xorq uv build, and the README shows the resulting layout with expr.yaml, expr_metadata.json, requirements.txt, and a wheel:
xorq uv build expr.pyFinally, catalog add copies the build under an alias. The -a flag is the alias, and the path argument is the build directory:
xorq catalog add builds/fa2122f6a9e9/ -a penguins-aggAfter that, the entry is addressable as penguins-agg. A human can browse it in the TUI, and an agent can pull it into context. The README does not show what output the add command prints on success, so do not expect a documented confirmation string. There is also an agent-first path: the Claude Code plugin marketplace adds xorq-labs/claude-plugins and installs xorq@xorq-plugins, which registers slash commands including /xorq:init, /xorq:catalog-explore, /xorq:composer, and /xorq:builder.
Where Xorq stops being the right tool
The content-addressed model has a sharp edge. The hash is computed over the computation and its inputs, so any change to the expression, the schema, or the input data produces a different hash and therefore a different entry. That is the point, but it also means the catalog grows rather than mutates. Nothing in the README describes how superseded entries are pruned, and the repository's justfile has a clean recipe that runs git clean, which is a blunt instrument for a directory holding catalog state.
Large inputs are the second edge. Git-annex support is listed as a design choice for large files, but annex adds its own operational surface: remotes, special remotes, and a sync step that is not the same as git push. The README does not document how a catalog behaves when an annex remote is unavailable, so treat that as unverified.
The third limit is scope. Xorq catalogs computation. If your organization needs owners, glossaries, access policies, and permissions enforced at query time, that is a different class of product, and the README says so directly. Xorq is also not a scheduler: it produces reproducible artifacts and a catalog, and the README's flow diagram ends at humans, CI, and agents rather than at a running job. If you want orchestration with retries and backfills, this is not that.
Xorq against metadata catalogs and against plain scripts
The README's own comparison is with Atlan, Collibra, and Unity Catalog. Those products inventory and govern assets you already have: descriptions, owners, glossaries, policies, permissions, and harvested lineage. Their cataloged unit is a metadata record over an existing table. Xorq's cataloged unit is a content-addressed expression plus a pinned environment, and the README's framing is that an entry is something you run, not something you read about. The two are complementary rather than competing, and the practical difference shows up at lookup time: a metadata catalog tells you a table exists and who owns it, while a Xorq lookup gives you a build directory you can execute.
The more honest alternative for most teams is what they already do: a Git repository of scripts plus a lockfile. That gets you version control and pinned dependencies. What it does not get you is a declarative spec of the computation, a hash that identifies it, or a lineage graph captured at build time. The trade is that a script repository needs no new tooling and no annex, and Xorq asks you to express pipelines in Ibis rather than in whatever pandas code you already have. If your transformations are already Ibis expressions, the migration is close to free. If they are not, that rewrite is the real cost.
Maintenance, licence, and what you are taking on
The repository is not archived, and the last push was on 2026-09-15. Releases have been frequent: v0.4.0 on 2026-08-25, v0.4.1 on 2026-09-01, and v0.4.2 on 2026-09-10. Version 0.4.2 is also the version pinned in pyproject.toml, so the published package and the repository agree. That cadence is real, but a pre-1.0 version number means the entry format and CLI surface can still move between minor releases, and the catalog format is the thing you would be committing to.
The licence is Apache-2.0, which is permissive and includes an explicit patent grant. That is a statement about the licence text, not legal advice; if you redistribute Xorq inside a product, have counsel read the NOTICE and attribution requirements rather than relying on this paragraph.
Upgrade cost concentrates in two places. First, each entry ships a pinned requirements.txt and a wheel, so entries built against an older Xorq keep their own environment and do not automatically pick up a newer runtime. That is good for reproducibility and bad for patching: a security fix in a dependency does not propagate to existing entries without rebuilding them, which changes their hashes. Second, the dependency floor logic in pyproject.toml is per-interpreter, with a comment warning that the >= '3.13' rows are only safe while requires-python caps below 3.14. Raising that cap requires a new row per interpreter, or lowest-direct resolution picks a release with no wheel for that Python. Plan for that when you upgrade Python.
Editorial conclusion
Adopt Xorq if you already write Ibis expressions and want agent output to land as runnable, hash-addressed entries in a Git repo rather than a folder of one-off scripts. Skip it if your pipelines are plain pandas with no Ibis layer, or if you need a governed metadata catalog with owners and policies, since Xorq catalogs computation, not assets. Before committing, verify three things yourself: that xorq uv build reproduces the same hash on a second machine, that the pinned requirements.txt in the build directory installs cleanly in your target sandbox, and how git-annex behaves when an entry exceeds your Git host's file size limit. The README does not document rollback for a bad catalog entry, so decide that policy before the first shared catalog exists.
Frequently asked questions
What is xorq-labs/xorq in Python?
It is a Python library and CLI that turns lazy Ibis dataframe expressions into content-addressed build directories, each holding a manifest plus a pinned environment, and stores those builds as entries in a Git-backed catalog. The README describes it as an executable, composable catalog for tabular data work, with a CLI for agents and a TUI for humans.
How do I install and build a first pipeline with Xorq?
Install the library with the examples extra, run xorq init -t penguins to scaffold a project, write an expression into expr.py, then run xorq uv build expr.py to produce a hashed build directory. Add that directory to a catalog with xorq catalog add builds/<hash>/ -a <alias>.
Which engines can a Xorq expression run against?
The README lists embedded engines DataFusion, DuckDB, SQLite, and pandas; warehouses Snowflake, Databricks, Trino, and Postgres; the lakehouse engine PyIceberg; and GizmoSQL over Arrow Flight. The same expression can target any of them, and into_backend moves data between them.
Community notes