the veil nl-veil v1.1.0

local-first · one binary · written in Zig

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.

Windows · macOS · Linux. No account, no key, no cloud — and nothing else to install.

1binary — server, desktop and CLI in one file
3clients over one API: web, desk, CLI
100+modules with annotated source docs
0bytes of telemetry leave the machine

Download

One file. Unzip it, run veil.

The server starts, the desktop app opens on top of it, and the CLI is the same binary with a verb after it. Nothing else to install.

Windows x86-64 veil-…-windows-x86_64.zip Download
macOS Apple Silicon veil-…-macos-arm64.zip Download
macOS Intel veil-…-macos-x86_64.zip Download
Linux x86-64 veil-…-linux-x86_64.zip Download

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.

    1. 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.

    2. 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.

    3. 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.

    4. 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.
    5. 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.

    6. 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.

    7. 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.
    8. 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.

    9. 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.

    10. 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.
    11. 22:05

      Collection. Files, the event stream, the metered spend, and the record of what was actually verified against what was merely assumed.

    12. 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.

    How it is built

    Four rules the engine is held to.

    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.

    Source document