Agentic coding, on your machine. Many minds, one shared memory.
the Veil is a desktop app for building software with AI. Unzip one file and run
veil — a native three-pane workspace opens, and you give it a goal. Where most
tools hand the job to a single assistant, this one can split it across a swarm of agents
working the same files in parallel. It ships its own model, so there is no key and no account, and
everything it learns stays in a data/ folder next to the binary.
Take the veil-… archive — not “Source code (zip)”, which GitHub staples to every release and which needs a compiler, and not veil-server-…, the headless build for remote boxes with no desktop app.
The binaries aren’t signed yet, so the machine will object once: Windows → More info → Run anyway; macOS → right-click → Open. Signing certificates are on the list.
The model comes too. The inference engine is compiled into the binary, so
the-veil-12b
is served by the server itself — no separate model runtime, no API key. Click download the
model in the app (or run veil model pull) and the whole thing works offline. Point it
at Ollama or any OpenAI-compatible endpoint instead whenever you would rather.
What’s in v1.1.0. The first stable release. Everything before it
— v1.0.0-alpha.1 through v1.0.1-beta-7 — went out labelled a
prerelease; this is the first build published without that label. Two things earned it, and the second one
is the reason the first was worth doing. A public URL. Log in with your own Cloudflare
account, flip one switch, and this veil is reachable at a Cloudflare address with no port forwarded and no
router touched. The default is confidential: an unlisted trycloudflare.com hostname,
shown only to the owner, minted fresh on every start, putting nothing on a domain you own. Use my
domain is the explicit alternative — a named tunnel behind a Cloudflare Access policy that
admits your login’s own email. The address is withheld until Cloudflare’s own resolver answers
for it, because a lookup made before the name exists is cached as a miss for the negative TTL of
1800 seconds: a probe four seconds early left one address unreachable from that machine
for half an hour while 1.1.1.1 resolved it fine. The costs are stated where you flip it — the switch
is owner-only, the tunnel refuses to start while open registration is on, registration is refused on
anything that arrived through a tunnel whatever the flag says, and off is verified rather than
assumed. A login made before this release is asked to sign in again, because the tunnel needs scopes the
old consent never requested.
And the parking. Putting a local server on the internet is only worth doing if it stays
up, and two things underneath it did not. The desktop app’s worker threads slept on the Io
runtime’s per-thread alert, which everything else on that thread also uses to wake mutex and
condition waiters; one stray alert parked the chat and poller threads for good, and the pane froze
mid-turn with the server perfectly healthy and “working.” still on screen. They sleep
through a non-alertable wait now, and a silent worker says so instead of leaving the last status frozen.
In the server, every accepted socket was dealt to one worker’s private queue, and a worker runs one
connection for that connection’s whole life — so a keep-alive client polling twice a second
pinned its worker and the next socket sat behind it while 127 others idled. Measured on an idle server:
about one new connection in twelve took 12.5–13 s to its first byte, while
keep-alive connections never stalled, which is exactly why it hid for so long. One shared dispatch queue,
and the same 75-second idle probe reports 0 stalls, worst 87 ms. The turn loop got stricter with itself
too: a claim of work with no tool call behind it is not done, a figure that came from nowhere is read off
the disk before it is stated, a reply cut at the output cap is continued rather than re-asked, a paste too
large to retype is written to a file first, and the verdict judges the goal you set instead of editing code
you never asked it to change.
Full release notes →
Earlier: beta-7 is where the Cloudflare login arrived — one click connects
your own account, and from then on the model picker carries your account’s live Workers AI
catalogue instead of a list shipped in the binary, your conversations and durable memories mirror
incrementally into an R2 bucket the veil provisions for you, and, if you grant the optional build scopes,
the assistant can write a Worker and put it on the internet at a real URL. The token is minted for your
account and sealed on your machine; there is no server of ours in the middle. beta-6 before it
made a long turn continue instead of starting over.
beta-7 notes →
Building it yourself instead — needs Zig 0.16+:
git clone https://github.com/gary23w/nl-veil
cd nl-veil
zig build run
Architecture
Thirteen parts, one request path.
The whole engine, laid out the way a request actually moves through it. Every node opens its annotated source document.
Hover a node to light its connections · drag to rearrange · click to read the module.
Keyboard: Tab to a node, ←↑↓→ to move it, Enter to open.
Source documents
Every module, annotated.
Generated from the tree and amended as the source moves: the server and its CLI, the server-side chat brain, and the native desktop app. Filter by module, path or file.
A cast, reconstructed
From one typed line to a booted deliverable.
What the engine actually did on one ordinary evening. The chips open the module that did it.
21:12
The goal arrives: one line, typed at the desk. The gateway checks the key at the door, and the audit log writes down the knock before anything answers it.
21:13
The supervisor detaches a worker. Casts run as separate processes; a cast survives the server that started it, the way a boat survives the dock.
21:14
The blueprint is drawn. The goal declares its file tree and every file gets an owner; no mind writes a teammate’s slice. Eleven minds open one shared memory and begin.
21:20
A write misses. The failure is recorded with its exact path before anything else happens. The fix comes later; the record comes first.
The miss is written down before the fix. That order is the whole method.
21:26
Edits from eleven minds meet in one file. Disjoint regions merge on their own. The same region is a conflict, and conflicts are said out loud, never papered over.
21:31
The checkpoint is rebuilt from the record: what completed, what’s blocked, what’s pending. No model is asked for its opinion — the ledger already knows.
21:33
Out of band, a reviewer reads the round’s real tool trace and mints a lesson into the live hive — only what the trace can ground, nothing a mind merely claimed.
A lesson nobody typed. It came off the trace.
21:38
The crawler brings back the outside. A fetched fact enters the hive only with a verbatim quote from the page that said it; the rest stays outside where it belongs.
21:40
Smoke test. The deliverable is booted and probed, not admired. Passing tests are not a working app; a working app is a working app.
21:55
The judge scores the cast. The governor reads the fitness curve, trims what idles, keeps what moves. A plateau is information, not failure.
The score is not the goal. Read the curve.
22:05
Collection. Files, the event stream, the metered spend, and the record of what was actually verified against what was merely assumed.
—
No cast is closed until somebody reads the record.
The memory underneath
The hive remembers in neuron-db.
Every observation any mind makes — a crawled fact, a failure with its path, a judge’s score — lands in one associative store that every other mind can reach. That store is its own project, and it runs without nl-veil.
One shared memory
Separate memories made polite strangers; one shared memory made a swarm. No private notebooks — the crawler’s facts, the builder’s failures and the judge’s scores all land where every mind can reach them.
In the engine: worker/oscillation.zig and worker/neuron/client.zig, both fail-open — if the store is down, the cast keeps running.
neuron-db, standalone
A typed-neuron associative store in Rust: recall in milliseconds over a million facts, plasticity that strengthens only what the evidence supports, and a browser build that runs the real core in WASM.
Not marketing copy — these are the constraints the code is reviewed against.
The engine is a floor, not a script
It never learns what a goal means; it learns how goals move. The day a use case gets hardcoded into the loop is the day the loop stops deserving the name.
Every mechanism is general. A branch in the engine that knows what it is building is a bug report.
A mind that shares is worth six that don’t
One hive, no private notebooks. Every observation any mind makes lands where every other mind can reach it — and that is measurable, not a slogan.
We counted.
Nothing mints but the trace
Outcome feedback strengthens what exists; it never creates what doesn’t. A win saturates a memory — it does not invent one, and a finished goal never comes back from the dead because a reward said it should.
Plasticity is a privilege of evidence.
A score is not the truth
A benchmark says the score is high. The smoke test says the app boots. Those are different sentences, and the engine pays the difference on every cast.
Knowing isn’t proof. The ledger records what was verified against what was merely assumed.