codeq: importing a git history into a Datomic database
Creates Datomic dbs from git repos
At a glance
- What is it?
- codeq is a Clojure application that walks a git repository commit by commit, loads each revision into a Datomic database and analyses the source, turning a version history into queryable data. It runs as a single uberjar against a Datomic transactor, it is not fast because it shells out to git constantly, and it has no GitHub releases at all.
- Who is it for?
- codeq fits a Datomic user who wants a repository's history, not just its current state, as datoms they can query: who changed a namespace, when a symbol first appeared, how a file evolved across commits. It is the wrong choice if you only need the current state of a repo, since a normal clone answers that, and the wrong choice for a team that cannot run a Datomic transactor, because that is a hard dependency rather than an optional one.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 128 days ago.
- What is it written in?
- Mainly Clojure, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Turning a version history into queryable data
The README describes codeq, whose name is pronounced co-deck, as a Clojure and Datomic application designed to do code-aware imports of your git repos into a Datomic db.
The phrase code-aware is the part that matters. A plain import of a git history into a database gives you commits, authors and file contents at each revision, which is a log. A code-aware import gives you the analysed structure of the code at each revision, so the symbols, namespaces and relationships inside a file become datoms alongside the commit that introduced them.
That is what makes the result interesting to query. A git log tells you that a file changed. A Datomic database built by codeq can tell you which entity in which namespace was retracted, when it was last asserted, and what it was asserted to, and it can answer questions across the whole history without replaying diffs.
The tool is a Java program that talks to a Datomic transactor over the network, so the shape of the workflow is: start the transactor, point the import at it, and it writes into a database it creates for you. The primary language is Clojure, the default branch is master, and the last push to the repository was on 2026-06-18.
One uberjar, one java command
The Usage section walks through the whole setup, and it is short enough to follow end to end.
You clone the codeq repo and run the build inside it:
lein uberjarLeiningen is the build tool, and the uberjar target produces a single standalone archive with everything bundled. Then you get Datomic Free, unzip it, start the Datomic Free transactor and follow the instructions for running the transactor with the free storage protocol.
With the transactor running, you change into the repository you want to import and run the jar:
cd theGitRepoYouWantToImport java -server -Xmx1g -jar whereverYouPutCodeq/target/codeq-0.1.0-SNAPSHOT-standalone.jar datomic:free://localhost:4334/gitThree things in that command line are worth reading. The URI scheme, datomic:free://localhost:4334, identifies the Datomic Free transactor and the port it is listening on. The final path segment, /git, is the name of the database to create, and the README says you can call it whatever you like. And the -Xmx1g flag is a heap limit of one gigabyte, which is a hint about how much the importer expects to hold while it works.
The import is of the local view of the repository, so the repository has to be a real clone on disk rather than a remote reference. That is consistent with the implementation, which shells out to git for the history.
What the import prints, and what the analyzer does
The README shows the expected output, and it is worth reading because it names the two phases of the run.
The first phase is the history:
Importing repo: [email protected]:clojure/clojure.git as: clojure
Adding repo [email protected]:clojure/clojure.git
Importing commit: e54a1ff1ac0d02560e80aad460e77ac353efad49
Importing commit: 894a0c81075b8f4b64b7f890ab0c8522a7a9986a
...
Import complete!Note that the repository is given a name, here clojure, separate from the database name git. That is what lets several repositories live in one database.
The second phase is the analysis:
Analyzing...
Running analyzer: :clj on [.clj]
analyzing file: 17592186045504
analyzing file: 17592186045496
Analysis complete!The analyzer is selected by file extension, and :clj is the Clojure analyzer running over the .clj files. The identifiers it reports for files are not paths but numbers, which is what you would expect from a database that stores entities rather than strings. The set of analysers is therefore what determines how much structure the import captures, and the Clojure one is the example the README gives.
This is where the data becomes queryable in a way a git log is not. The commits are the history, and the analysed entities are the code as it was at each point in that history.
The cost of shelling out to git
The README is candid about performance, and the sentence is worth quoting in full because it describes the implementation rather than apologising for it.
The import is not too peppy, since it shells to `git` relentlessly, but it imports e.g. Clojure's entire commit history in about 10 minutes, plus analysis.
That gives you the shape of the tool. The importer does not read the git object database directly, it invokes the git command line, over and over, once per piece of information it needs about each commit. That is a simple and portable implementation, and it inherits git's correctness for the hard parts like packfile handling, but it pays a process spawn per operation.
Ten minutes for the entire Clojure history is a useful yardstick, because Clojure's history is not small. For a repository with a few hundred commits the run will be quick, and for a repository with a hundred thousand it will be long, and the time scales with the number of commits times the number of git invocations per commit.
The practical planning point is that this is a batch job, not something you run repeatedly during a work session. It is also the reason the command asks for a gigabyte of heap, since the analysed entities accumulate as the import proceeds.
On the flip side, shelling out means codeq inherits whatever git is installed on the machine, and the import reflects the working tree's view of the repository rather than anything the remote knows.
One database, many repositories, incremental re-imports
Two properties make the tool usable in practice rather than as a one-off curiosity.
The first is that you can import more than one repo into the same db. The database name in the URI is yours to choose, so two projects can share a database, and each repository carries its own name inside it, the clojure in the example output. That is what makes cross-repository queries possible in principle, which is the sort of thing a Datomic user would want and a set of git clones cannot give them.
The second is that re-importing is incremental. You can re-import later after some more commits and they will be incrementally added.
So the intended workflow is a scheduled job rather than a one-time script. You clone or fetch the repository, run the import again, and the new commits are appended with their analysis. The database accumulates rather than being rebuilt.
That design also explains the performance note. If the import were a full rebuild, an inefficient implementation would merely be slow. With an incremental model, the previous work is preserved and only the delta is processed, so the cost is proportional to what changed rather than to the size of the history.
The README also mentions that you can connect to the same db URI with a peer, or just start the Datomic REST service and poke around, which is how you get at the data once the import has run.
Reading the result through the REST service
Once the import is done, the database is a normal Datomic database and can be queried the usual ways. The README describes two routes: connect to the same db URI with a peer, or start the Datomic REST service and look around.
The REST route is the one that needs no extra machinery:
cd whereverYouPutDatomicFree bin/rest -p 8080 free datomic:free://localhost:4334/That starts the REST service on port 8080 against the free storage at the transactor's port. The README then says to browse to localhost:8080/data/, where you should see the `free` storage and the `git` db within it.
That endpoint is the index of what is in the database, and for a first look it is the fastest way to confirm the import did what you expected, since it shows the storage and the databases rather than the contents of a single entity.
For getting oriented on the shape of the data, the README points at a schema diagram, and says it will help you get oriented. That diagram is the schema the import produces, which is the part you need before you can write a query: the datomic entities for commits, files, entities and their relationships, and the attribute names you will use in your queries.
Two more pointers are given for depth. There is an intro blog post on the Datomic blog and a wiki for the project, and the repository carries a doc directory and an examples directory with a clojure-and-contrib example and an examples/src tree, so there is sample data to look at before you point the tool at your own history.
An Eclipse Public License project from 2012
The License section says Copyright 2012 Metadata Partners, LLC and Contributors. All rights reserved, and that it is distributed under the Eclipse Public License, the same as Clojure.
That is worth pausing on twice. The repository listing records the licence as one that GitHub cannot classify, while the README states EPL plainly and the repository root carries epl-v10.html, the licence text. The EPL is a file-level copyleft, so a fork or a derived work carries obligations, unlike the MIT or Apache licences that most comparable tools use. It is also the same licence as Clojure itself, which is consistent with a Clojure tool.
The date is 2012, and the README's blog post link is from October 2012. The tool was written against a Datomic of that era, and the Datomic Free edition it depends on has been a moving target since, so the URI scheme and the transactor's behaviour are the parts most likely to have shifted.
The repository itself is small and conventionally laid out, with src, test, doc and examples directories, a project.clj for Leiningen, and the licence file. There are no GitHub releases, so the version in use is the SNAPSHOT in the jar name, codeq-0.1.0-SNAPSHOT-standalone.jar.
The maintenance signal to read is the last push on 2026-06-18 against a 2012 copyright line. Something has been touched in the repository, but there is no release history to show whether the code moved with it, and a project with no tagged versions is one where you are running whatever is on a branch rather than a version you can depend on.
Editorial conclusion
codeq fits a Datomic user who wants a repository's history, not just its current state, as datoms they can query: who changed a namespace, when a symbol first appeared, how a file evolved across commits. It is the wrong choice if you only need the current state of a repo, since a normal clone answers that, and the wrong choice for a team that cannot run a Datomic transactor, because that is a hard dependency rather than an optional one. Verify first the Datomic Free storage protocol version your transactor speaks, since the README's URI scheme is specific to it, that the JVM has the heap the run command asks for, and that the licence position is acceptable, since the README states the Eclipse Public License while the repository listing records no recognised licence.
Frequently asked questions
What does codeq do?
It is a Clojure and Datomic application that does code-aware imports of git repositories into a Datomic database, loading each commit and analysing the source at each revision so that the history becomes queryable data rather than a log of diffs.
How do I run codeq?
Clone the repository, run lein uberjar inside it, get and start a Datomic Free transactor on the free storage protocol, then from the repository you want to import run java -server -Xmx1g -jar codeq-0.1.0-SNAPSHOT-standalone.jar datomic:free://localhost:4334/git. The final path segment is the name of the database it creates.
How long does importing a git repository take?
The README says the import is not too peppy because it shells to git relentlessly, but that it imports Clojure's entire commit history in about 10 minutes, plus the analysis time. The second phase runs an analyzer selected by file extension, for example the :clj analyzer over .clj files.
Can I import several repositories into one Datomic database and re-import later?
Yes. You can import more than one repo into the same db, each repository being given its own name within it, and you can re-import later after some more commits and they will be incrementally added.
How do I read the imported data?
Connect to the same db URI with a peer, or start the Datomic REST service with bin/rest -p 8080 free datomic:free://localhost:4334/ and browse to localhost:8080/data/ to see the storage and the imported database. The README also links a schema diagram to help you get oriented.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/datomic-codeq)Was this useful?