The Zero-Dollar AI Stack




Most AI coding and research tools make one decision for you before you have typed a single prompt: which model you use, and whose server your code goes to in order to use it. Zorp does not make that decision. It is a Rust binary that runs on your machine, talks to whatever model endpoint you point it at, OpenAI, Anthropic, or anything else, local or not, and has no opinion about which one you pick.
That is not a philosophical stance. It is a specific, checkable design choice, and this post is about what it actually gets you: any model, a genuinely zero-dollar path if you want one, and a local-by-construction guarantee on the parts of the system that do not need a network at all.
Why this is not a niche preference
81%of developers have security or privacy concerns about AI tools
Security and privacy concerns rank as the single biggest deal-breaker for AI tool adoption among developers surveyed, ahead of every other objection. 84% are using AI tools anyway, which is the actual tension this stack is built to resolve: use the tool, keep the choice about where your code goes.
Source: Stack Overflow, 2025 Developer Survey (AI section)
Any model, because the transport does not care
Zorp talks to a model through one interface: an OpenAI-compatible chat
completions endpoint, plus a native path for Anthropic. That single
interface is what Ollama, LM Studio, vLLM, and oMLX all speak, so
“local model” is not a special mode bolted onto the side. It is the same
code path as GPT-4o or Claude, pointed at 127.0.0.1 instead of a cloud
domain.
Same three variables, four different backends
shell
export ZORP_BASE_URL="https://api.openai.com/v1"
export ZORP_API_KEY="sk-..."
export ZORP_MODEL="gpt-4o-mini"
cargo run -- "Summarize the second law of thermodynamics in one sentence."shell
ollama serve
export ZORP_BASE_URL="http://127.0.0.1:11434/v1"
export ZORP_MODEL="qwen3:4b"
cargo run -- "Summarize the second law of thermodynamics in one sentence."No ZORP_API_KEY. Ollama serves an OpenAI-compatible /v1/models endpoint, so it is a preset, not a special case.
shell
export ZORP_BASE_URL="http://127.0.0.1:8000/v1"
export ZORP_MODEL="<whatever that endpoint lists>"
cargo run -- "Summarize the second law of thermodynamics in one sentence."Any server that speaks OpenAI-compatible chat completions works the same way. The web UI's settings panel lists the models the endpoint actually reports, rather than a hardcoded menu.
shell
export ZORP_API_KEY="sk-ant-..."
cargo run -p zorp-agent -- --provider anthropic --model <model> "<task>"The one native path outside the OpenAI-compatible transport, because Anthropic's API shape differs enough to warrant its own client.
The web UI’s settings panel makes the same choice without an environment
variable: pick a provider, point it at a base URL, choose from the
models that endpoint actually lists. A setting saved there beats the
matching ZORP_* variable, which beats the built-in default, and every
field says which of the three it came from. The API key is the one
exception: it lives in memory for the life of the server process and is
never written to disk unless you also set it in the environment yourself.
Zero dollar, precisely
Two separate costs get bundled together in most “AI stack” pricing, and Zorp is worth being exact about which one it removes.
The software costs nothing, full stop. Zorp is MIT licensed, no
subscription, no seat, no paid tier anywhere in the project. The install
script pulls prebuilt binaries for your platform, verifies the published
checksum, and puts zorp, zorp-agent, and zorp-web on your machine
with no Rust and no Node required:
curl -fsSL https://raw.githubusercontent.com/aviskaar/zorp/main/install.sh | bash
Inference costs whatever your model costs, which can also be zero.
Point ZORP_BASE_URL at a frontier API and you pay that provider per
token, exactly as you would calling it directly. Zorp adds no markup and
no toll of its own. Point it at Ollama, or LM Studio, or vLLM running on
your own GPU, and the marginal cost of every completion is your
electricity bill. The docker-compose path brings a full local stack up
in one command, UI, agent server, and an Ollama sidecar together:
ZORP_WEB_TOKEN=$(openssl rand -hex 16) docker compose up --build
docker compose exec ollama ollama pull qwen3:4b
docker compose exec ollama ollama pull qwen3-embedding
That is a genuinely zero-dollar AI research and coding stack: free
software, running a free model, on hardware you already own. It is also
not the only option. The same binary, the same evidence record, the same
validate/investigate/co-write/deliver loop runs unchanged against
a frontier model the moment a question needs the ceiling only a frontier
model currently offers. Nothing about switching costs you a rewrite,
because nothing about the harness assumes which one you picked.
Local by construction, not by promise
“Your data stays local” is a claim almost every AI product makes and almost none of them can show you the code for. Zorp’s conversation search is a specific, narrow example of what actually enforcing it looks like, rather than just asserting it.
The recall feature lets the web UI search everything you have ever
asked Zorp, by meaning, entirely on your machine. Getting that right
took four separate, layered checks, because any one of them being wrong
on its own would leak a conversation to the network:
The endpoint has to be a loopback literal or localhost, and it has to still resolve there
Naming a remote host in the embedding endpoint variable does not get you a remote embedder. It gets you a refusal that names the host. The check is on the resolved address, not the string you typed.
The HTTP client can only reach the addresses that resolution returned
A resolver that runs after the check passes could still be tricked into pointing somewhere else. The client is restricted to the addresses already validated, through a resolver that performs no lookup of its own at request time.
Redirects are refused, not followed
A loopback endpoint that responds with a 302 to somewhere else would otherwise take your conversation with it. The client does not follow that redirect; it fails instead.
Proxy detection from the environment is switched off
An HTTP_PROXY variable set anywhere on the machine, by another tool, another shell profile, another process, cannot silently route a loopback call through a third-party server. The embedding client ignores it.
There is no remote embedding provider, no flag that adds one, and no
fallback when the local model is missing. If nothing answers on
127.0.0.1, the search box says so and searches nothing, rather than
quietly starting to work by phoning out. A corpus of everything you have
ever asked an agent that reads your files is exactly the thing a
“local first” claim should mean, and here it is enforced four different
ways rather than asserted once in a privacy policy.
The same posture shows up everywhere else in the stack, not just in
recall:
- The web UI binds to loopback by default. Reaching it from anywhere
else requires an explicit
--token, and it refuses to start without one, because a reachablezorp-webis agent-driven shell access to whatever the process can see. - Web search is the one built-in tool that sends anything over the network, and it is off by default in both the CLI and the browser. It asks for approval before it runs, the same as any MCP tool would, and a project can withhold it entirely.
- The chat UI’s own fonts are vendored into the repository rather than loaded from a font CDN, so the interface renders the same on a machine with no network at all and makes no request to a third party just to draw its own text.
Built for how engineers already work
A few details in here specifically are aimed at the person reading this in a terminal, not a boardroom.
Skills you already wrote work here unmodified. Zorp reads the same
skill format Claude Code does: a directory with a SKILL.md, YAML
frontmatter, a markdown body. Nothing to port, nothing to convert.
---
name: code-review
description: Review a diff for correctness bugs. Use when asked to review changes.
---
Read the diff first, then the surrounding code. Report findings by
severity, and say when you are unsure.
A skill can only add guidance, never permissions: it cannot enable a tool, loosen an approval preset, or reach past the command denylist, and a body over 64 KiB or one that tries to resolve outside its own directory gets skipped rather than loaded.
Every write or run asks first. Tool calls that touch the filesystem
or a shell go through an approval prompt before anything happens. A long
run can stand those prompts down for one session, and the toolbar says
so the whole time it is on; it still cannot get a denylisted command
past the policy underneath. MCP servers you connect declare a trust
level explicitly in .zorp/mcp.toml, rather than inheriting a default.
Extend it with MCP, not with a plugin API to learn. Any MCP server you already run connects the same way tools do everywhere else. Memory across sessions is open-context, a separate MIT-licensed project, connected as an MCP server rather than baked in, so it stays optional and swappable instead of becoming a dependency Zorp carries forever.
The part this all sits under
None of the above is a separate “developer mode” bolted onto a hosted
product. It is the substrate the actual research capabilities run on.
validate, investigate, co-write, and deliver, the loop that turns
a question into a pre-registered investigation and an evidence record,
run against whatever model you configured in the sections above, local
or frontier, with no code path that treats one as first-class and the
other as an afterthought.
Zorp ships 24,965 lines of Rust across a handful of crates, 605 tests, and an MIT license, all measured the same way the homepage measures them: checkable against the repository, not asserted here.
Where this actually is
Zorp is pre-alpha, and this post is not going to round that off. The
install script and the OpenAI-compatible transport work today. The
published Docker image does not pull yet, the package is published but
still private, tracked in
issue #30, so docker build
or the install script are the working paths until that flips. The
research feature (validate/investigate/co-write/deliver) needs
a source build today, because zorp-track bundles DuckDB and is not yet
in the prebuilt binaries.
None of that changes the shape of the argument. The stack underneath is free, it runs any model that speaks an OpenAI-compatible API or Anthropic’s, and the parts of it that do not need the network do not touch it. That is a specific set of engineering decisions, not a slogan, and every one of them above is something you can go read in the repository yourself.