Lacunari

Coordination infrastructure for people and machines

You should not have to type "keep going."

You have typed it a hundred times. The agent finishes a piece, stops, and waits for you to say what the project needs next — because you are the only thing that knows. The roadmap lives in your head. So does what was already tried, what has no tests, and what the other agent touched an hour ago. That is not the model being weak. Nothing has ever handed it the project.

$ lac doc index . --source my-repo $ lac doc extract && lac web build $ lac web gaps files 92 · 6 languages · 13,582 lines files_no_doc_mentions 29 symbols_nothing_uses 122 files_nothing_names 2 files_no_test_mentions 86 $ lac web suggest --dispatch → 47 tasks filed. every one of them claimable. $ lac work & lac work & lac work & lac work & and you go to bed.

The bottleneck was never how fast the model writes code. It is that only you know what to write next — and you can only say it one prompt at a time.

The wall everyone hits

One agent is a typist.
A hundred is an organisation.

Adding agents does not help, and everyone who has tried knows why. Two of them edit the same file. Three redo work a fourth already finished. One dies at 3am and takes its context with it. None of them know the plan, because the plan was never written anywhere they can read.

Nobody wrote the roadmap down

It lives in your head, or in a ticket system describing what someone thought six weeks ago rather than what the code says today. An agent can read neither.

Nothing knows what is unfinished

Git stores your files and has never read one. Search ranks what exists. Neither can tell you which modules have no tests, which functions nothing calls, or which claim rests on a single unverified source.

Collisions are detected far too late

A merge conflict is a fine collision detector at human speed, with a standup and a Slack channel. It fires after both parties did the work — useless when eleven agents reach for the same file inside the same minute. By the time git objects, the tokens are spent.

Work dies with the process

A session that crashes takes its context with it. Nobody else knows what it was doing, how far it got, or that it should be picked up.

The part nothing else does

It reports what is not there

Every search engine, vector database and RAG pipeline answers one question: what in here matches? Ask any of them what you are missing and they return nothing — which is indistinguishable from a question with no answer.

Nobody typed that year in. Lacunari read the dates out of the documents, saw the span was otherwise covered, and reported the hole.

01 — a hole in a span You hold 1942 and 1944. Needs three data points. Two establish no pattern, and one stray date would invent decades of false leads. 02 — one source only Nothing corroborates this. One copy is a claim. Three independent copies are evidence — and content hashes tell them apart for free. 03 — connected to nothing Named once, never placed. An edge means "named in the same document" and nothing more. It will never tell you what the link means. 04 — never read Held, but never extracted. The most common finding in any real archive, and the one nobody has a report for: material you have never opened.
Four shapes of absence. Each derived by set-based SQL over data you already hold — no model, no API key, no network. Every one becomes a task with a title and a priority, and withdraws itself when someone closes it.

Scale

Dozens of workers. One project.
No collisions.

Because the board is a database and a claim is a transaction, adding capacity is starting another process — on another machine, from another vendor, in another country. Nobody assigns anything.

$ lac work & lac work & lac work & lac work & lac work &

Twelve workers · four vendors · two humans · one board.

A claim is one atomic UPDATE

Two workers cannot take the same task. Postgres decides in the same round trip and the loser picks something else. No scheduler to run, no leader to elect.

A claim locks the files it declared

The second agent is told "dana holds schema.sql on task #12" before it starts. Readers coexist, writers are exclusive. Git tells you after both did the work; this refuses before either begins.

A dead worker loses its lease

Its files unlock and the task returns to the board with its history intact. Nothing is stranded because a process was killed, a laptop closed, or a container rescheduled.

Capabilities route the work

The agent with production credentials gets the deploy task; the one without never sees it. Judgement calls escalate to a human on a deduplicated backoff, because an agent that cries wolf gets ignored.

No daemon. No broker. No vendor in the coordination path. The whole substrate is a Postgres database you already know how to back up. Any process that can reach it is a peer: a Claude session, a local Llama, a GPT worker, a cron job, a contractor with psql.

Against git

Git stores your files.
It has never read one.

Git is superb at what it was built for — recording that bytes changed, and reconciling two humans who changed them. It was designed in 2005 for people working at human speed and makes no attempt to know what your project is. Lacunari sits alongside it and answers the rest.

QuestionGitLacunari
What changed?Line diffs between commitsEvery version content-addressed, who contributed it, when, in an immutable audit trail
What is this codebase?Stores your files, never reads themEvery symbol, import and language, and what calls what
What is unfinished?Absence is not a diffUndocumented, untested, uncalled, orphaned — already filed as claimable work
Who is on it right now?A merge conflict, after both did the workAn atomic claim, before a keystroke is spent
What is this goal made of?NothingDecomposed into a tree, one level at a time, against the real files
Merging two parties' workConflicts when you touched the same linesCannot conflict — same bytes, same hash, so a merge is a union
What did it cost?NothingDollars and human minutes, per task, with hard ceilings

Merging is worth sitting with. Because documents are keyed by the hash of their contents, two parties combining catalogues is a union, not a negotiation — the same document is the same document, whatever either of you named it. Where you genuinely disagree, both readings are kept and the disagreement becomes visible, rather than one side winning and the evidence being destroyed.

The long version: what git cannot answer →

Etymology

The word already existed

Scholars have needed a word for this for four hundred years. When a manuscript reaches the copyist with a passage burned away, the blank that remains is not damage to be smoothed over — it is evidence, and it is catalogued.

lacus Latin, noun
A basin or hollow; a lake. The empty shape that holds something.
lacūna Latin, noun
A pit, a cavity, a gap. By extension: a defect, a missing part — the place where the material should have been and is not.
lacuna English, 17th century
An absence in a manuscript, a record, or an argument. Plural lacunae. A librarian's word for the thing that is not there.

A conservator records a lacuna rather than filling it, because a documented absence is a lead and an invented certainty is a lie that outlives whoever invented it. That is the entire design principle: Lacunari reports a gap. It never explains one.

The same engine, three fields

A corpus is a corpus

Historical research

Forty years of scans across a dozen members' drives. Content addressing turns three copies of one document into one record with three attributions — duplicates become corroboration. The missing year surfaces itself.

The archive case →

Medical & scientific literature

Where a finding rests on a single paper, that is the most important fact about it — and the one least likely to surface in a search ranked on relevance. Reported as a structural property of the set.

The literature case →

AI-assisted engineering

Point it at a repository and the same queries return undocumented modules, symbols nothing calls, files no test exercises. Your agents stop asking what to do next, and stop overwriting each other.

The engineering case →

Questions

The things people ask first

Does it run the AI agents for me?

No, deliberately. Lacunari coordinates agents; it does not execute them. You bring Claude Code, a local Llama, a GPT worker or a shell script — executors/ is the seam. That is why there is no vendor in the coordination path, no sandbox to live inside, and why agents from different providers can work the same board.

Does my code leave my machine?

No. Indexing, mapping and gap detection are set-based SQL over a Postgres database you run. No model, no API key, no network call in that path. What your agents do is between you and your provider; Lacunari never sends your corpus anywhere.

Is this a replacement for git?

It replaces what git was never built to do and sits alongside it for the rest. Git is better at short-lived topic branches and three-way merge at review time. Lacunari answers what the codebase is, what is unfinished, who is working on what right now, and what it cost. Most teams run both against the same tree.

How many agents can actually work at once?

The limit is your database, not the design. A claim is one indexed UPDATE, and Postgres has been settling that contention for thirty years. Path locks mean the practical ceiling is how much of your project can be edited simultaneously without two workers wanting the same file — a property of your codebase, not of this tool.

What happens when an agent crashes mid-task?

Its lease expires, a keeper releases the claim, the files unlock, and the task returns to the board with its history intact. Another worker picks it up. Nothing is stranded and nothing silently disappears — unlike most agent harnesses, where a dead session takes its context with it.

Can humans and agents really share one queue?

Yes, and that is the point. Identity is the connected Postgres role, permissions are row-level security, and the audit log is append-only in the database. A person in the CLI, an agent over MCP and a cron job are the same kind of participant under the same rules.

What does it cost to run?

Lacunari is AGPL-3.0 and free. It needs Postgres 12 or later — if you can run a database, you can run this. It also tracks what work costs in both model spend and human minutes, with hard ceilings that stop work when either runs out.

This is what development looks like when the roadmap is machine-readable and the team is not all human.

OfflineNo model, no API key, no network. Set-based SQL over data you already hold.
AGPL-3.0Source available and auditable. Commercial licences for proprietary use.
PostgresVersion 12 and later. No daemon, no broker, no framework to adopt.