Show HN: An open-source multi-tenant, AI-native software factory Missing Studio released Eva 0.1.0, an open-source, multi-tenant, AI-native software factory that logs every interaction to disk as evidence, with the terminal chat client showing only what is already recorded. The tool, built in Go 1.26, supports Anthropic and OpenAI providers, and its roadmap includes a control plane for coding agents with verifier-scored races, though current version lacks file, test, and shell tools. Evidence, not claims. An autonomous, multi-tenant, AI-native software factory Most AI tools tell you what they did. Eva writes it down first. Every question you ask, every answer that comes back, every retry, and every token counted is appended to a file on your disk as it happens. What you see on screen is read back out of that file. If Eva shows you an answer, the file already had it. There is no second version of events. That sounds like a small thing. It is the whole design. bash $ eva EVA Evidence, not claims version 0.1.0+e839c8a model claude-sonnet-4-5 branch main cwd ~/code/eva type /help for slash commands › what's the difference between a cache write and a cache read? A cache write stores your prompt prefix so later calls can skip re-reading it. A cache read is one of those later calls hitting the stored copy… › /cost session 1.2k in / 340 out · cache 2.0k write / 1.1k read · cost unreported Notice cost unreported . Neither Anthropic nor OpenAI returns a dollar figure with a response. So Eva says so, rather than multiplying tokens by a price it looked up somewhere. A number you can argue with a bill about has to come from the bill. Note Eva is early. Today it is a good terminal chat client with a very carefully built foundation. It can read your question and answer it. It cannot read your files, run your tests, or touch your shell — there are no tools yet. Eva is being built toward a control plane for coding agents. Work arrives as a spec with acceptance criteria a machine can check. Several harnesses race the same spec in isolated environments. A verifier Eva owns decides what actually passed, and the whole race is scored from the same record everything else is scored from. The reason for building the foundation this carefully first is the ladder in docs/explanation/the-ladder.md /missingstudio/eva/blob/main/docs/explanation/the-ladder.md . The usual story goes model → agent → harness → factory. That chain skips five rungs, and each omission is a known way this fails: | The rung that gets skipped | What breaks without it | |---|---| Workflow | Control flow is handed to the model before the model can hold it | Environment + verifier | Nothing tells the agent it is wrong, so it never converges | Scheduler + spec format | More agents is not a factory. A factory needs a queue and a spec | Learning loop + economics | No evals, and no cost per merged change | Intent + authority | Nobody owns what was decided, and nobody answers for it | Nineteen stages, each with an exit test it can fail. One of them is built. The plan is a draft; the stage that shipped is not. You need Go 1.26 https://go.dev/dl/ or newer. Nothing else. git clone git@github.com:missingstudio/eva.git cd eva go build -o eva ./cmd/eva That produces a single binary in the current directory. Put it on your PATH if you want it everywhere. Eva talks to Anthropic and OpenAI. Pick one. export ANTHROPIC API KEY=sk-ant-... ./eva That's the whole setup. Anthropic is the default, so nothing needs configuring. For OpenAI, create a settings file and name the provider: ./eva init writes ~/.eva/config.toml export OPENAI API KEY=sk-... provider name = "openai" One line is enough. The model and the key variable follow the provider you picked, so you get gpt-5.6-terra reading OPENAI API KEY without saying either out loud. If you pay OpenAI monthly, you can use that instead of an API key: ./eva login It prints a URL and a short code, you approve it in a browser, and the credential is saved to ~/.eva/auth.json . Then set the mode in ~/.eva/config.toml : provider name = "openai" auth = "subscription" Check what Eva will actually use at any time: ./eva auth status provider: openai auth: subscription store: /Users/you/.eva/auth.json login: account acct 1a2b, valid until Mon, 11 Aug 2026 09:14:00 IST Important auth decides, and nothing overrides it. If it says subscription , an exported OPENAI API KEY is ignored, and eva auth status will tell you so rather than quietly using it. Most tools try the environment first, which is how people bill the wrong account for a month without noticing. why /missingstudio/eva/blob/main/docs/adr/0031-a-credential-has-a-mode-and-the-mode-alone-decides.md Your key is never written to a settings file. Eva reads it from the environment, or gets it when you log in. It never appears in the history file, a log, or anything sent to a model. Run eva with no arguments and type. Answers stream in as they arrive. | Key | What it does | |---|---| enter | Send | shift+enter or alt+enter | New line without sending | ctrl+c | Stop the answer in progress, keep what you typed | ctrl+d | Quit | tab | Finish a slash command | shift+↑ ↓, pgup pgdn | Scroll back | ctrl+home / ctrl+end | Jump to the top / back to live | Interrupting is safe. The conversation stays usable and the history file records that you stopped it. Type / at the start of a line. These are handled locally and never reach a model, so they cost nothing. | Command | What it does | |---|---| /help | List the commands | /cost | What this conversation has cost so far | /clear | Start a fresh conversation | /model | Show which model is answering | /model gpt-5.6-terra | Switch models, keeping the conversation | /login | Explains that logging in happens outside the chat | /model swaps the model mid-conversation without dropping context, so the next answer still knows what you talked about. Eva doesn't keep a list of valid model names, because a list compiled last month would reject a model released last week. If the provider doesn't recognise the name, that answer fails and tells you. /clear starts a new conversation rather than deleting messages from the current one. Your old messages are still in the history file either way. why /missingstudio/eva/blob/main/docs/adr/0019-clearing-the-transcript-opens-a-new-session.md eva -p answers one question, prints it to stdout, and exits. eva -p "explain this error" answer.md || echo "that failed" It exits non-zero when the answer failed, and writes the reason to stderr. That makes it safe to use in a pipeline: stdout is the answer and nothing else. › what is this? No response — the credential was refused provider.auth is "api key", so what anthropic refused is the key in $ANTHROPIC API KEY Two lines, both true. The first names the kind of failure, in Eva's own words rather than the vendor's error document. The second appears only when Eva checked something about your machine, and only when that fact leaves exactly one next step. A missing login says run eva login because that is certainly the fix. A refused key says which key was sent and stops, because revoked, wrong organisation, and suspended account all look identical from here. Sending you to fix something that was never broken costs you every later hint that would have been right. why /missingstudio/eva/blob/main/docs/adr/0041-a-remedy-is-checked-and-the-layer-that-can-check-it-is-not-the-layer-that-says-it.md | Command | What it does | |---|---| eva | Open the chat | eva -p "