Running it and paying for it
Which providers and models, how to run locally, what it costs, what stops a runaway bill, and what breaks.
This page is the operational half of the FAQ: what you can point it at, what that costs, what actually stops it, and what happens when the thing you pointed it at stops answering. The budget answers are the ones worth reading carefully, because the mechanism is narrower than most people assume and two separate safeguards are usually mistaken for one.
Which providers and which models?
Which model vendors can dev3d talk to? Five provider ids ship: deepseek, openai, openrouter, anthropic and local, each enabled by one environment variable. The curated table describes twelve models across those five, and live discovery can add models the table has never heard of.
Why
The provider ids and the key that enables each one are the whole configuration surface. DEEPSEEK_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY and ANTHROPIC_API_KEY are the four credential names; the fifth, local, is special because it is keyless and counts as configured on the strength of its base URL alone. Anthropic is spoken over the Messages API rather than the OpenAI shape, which is why it is a distinct adapter rather than a base-URL override.
Two things about the catalogue are easy to get wrong, and both are deliberate. First, the curated table is an overlay, not a roster: at boot, unless discovery is switched off, the office asks each configured provider what it actually serves and treats that as membership. A model the table has never heard of is still routable, flagged as unrated, and its tier is inferred from the vendor's own published price or, failing that, from its name. Second, a provider with no key contributes no candidates at all — that filtering happens in the provider registry before the router ever sees a catalogue, so an unconfigured vendor is invisible rather than merely deprioritised.
The models themselves are chosen per turn by the router, not assigned per role. A role's ModelPolicy names tiers — nano, small, standard, strong, max — plus a hard floor and ceiling, optional per-task-class overrides, an escalation threshold and a per-turn output cap. The router filters on capability first, then resolves a target tier from the posture, then scores the survivors with a weighted formula in which cost is one term among several. That is why the same employee can be served by two different models on two consecutive turns, and why every turn records the decision and the reason. The full mechanism, including the real rejection strings, is on Model routing.
Can I run it entirely on a local model?
Can dev3d run with no cloud provider at all? Yes. Any OpenAI-compatible runtime you already run — Ollama, vLLM, LM Studio and friends — becomes a provider by setting DEV3D_LOCAL_BASE_URL, and no key is required because the local provider is declared keyless. The caveat is that it is still a live provider, so the office is in live mode and turns are priced against the curated estimate.
Why
Setting DEV3D_LOCAL_BASE_URL is enough, and it is worth understanding why: the local provider declares keyless: true, and its presence is what makes it count as configured. The default value is http://127.0.0.1:11434/v1, which is where Ollama listens, so a runtime on its default port needs nothing beyond that line. DEV3D_LOCAL_API_KEY exists for runtimes that do check a token, and is otherwise unnecessary.
Two honest caveats, and the first one bites. The curated table describes exactly one local entry, at tier small, with a deliberately modest quality rating — because its real capability depends entirely on what you loaded and nobody has measured it. If your local model is stronger or weaker than that, turn discovery on so the provider's own model list is used, or correct the entry in the Settings page. Second, because the local provider counts as configured, setting this variable also moves DEV3D_LLM_MODE=auto to live. That is not a bug, but it does mean one combination does not exist: a local runtime and a keyless mock demonstration at the same time. Pick one, or force the mode explicitly and accept that the boot reason will tell you it was forced.
The nearest thing to a free live office is a local model, not mock mode. Mock mode costs nothing and exercises the entire pipeline, but its answers are scripted — deterministic text that quotes your brief back rather than reasoning about it. A local model reasons, and costs only electricity. If you want to see what the office does with real model behaviour and spend nothing, that is the configuration.
What does it cost to run?
What is the price of dev3d? The software is free software with no fee, no account and no metering. Your cost is your provider bills, and the prices the office reasons about are curated estimates for ordering candidates, not billing truth — the real number is on your vendor's invoice.
Why
Every turn is a real API call to a real vendor, priced per million tokens in and out. A run's total is therefore the sum of its turns, and the number of turns is not fixed: it depends on the pipeline the brief selects, how many employees a stage has, how long each takes, how many tool round trips a model asks for, and whether a review loop sends work back to the builders. A three-stage quick-answer run and a ten-stage product-build run are not close to each other, and that difference is the reason to name the pipeline explicitly the first time you submit something.
What dev3d will not do is pretend to know your invoice. The catalog prices exist so that routing and cost reporting can be ordered plausibly — the source says so in as many words — and the Settings page is where an installation corrects them. Two direct consequences: a cost figure in the console is a routing estimate rather than an account, and a model discovered from a provider that publishes no prices has its cost inferred or defaulted to zero, which makes it look cheaper than it is until you correct it. Treat the spend column as a decision aid and the vendor dashboard as the truth.
The way to control the number is not to avoid expensive models; it is to let the router spend them where they matter. That is the entire design thesis: a one-line intake summary and a file-level architecture decision are not the same purchase, and billing them at the same rate is how an agent workflow gets a reputation for being expensive without anyone being able to say which part was. The posture — cheap, balanced or quality, defaulting to balanced — moves the target tier up or down for every turn, and each role's floor and ceiling bound what any posture can do to it.
What actually stops a runaway bill?
Is there a hard spending limit? There are two mechanisms and they are not the same thing. A hard ceiling is checked before each stage and fails the whole run when it is crossed; a soft gate asks a human once per run, between stages, whether to keep going. Neither is a per-turn cut-off, and one environment variable that looks like a third is read and then never used.
Why
Take the ceiling first, because it is the one that actually stops money. Its value is the floor's own budget.defaultRunUsd, which defaults to 5, overridable per submission with budgetUsd. It is checked before each stage with a greater-or-equal comparison, and crossing it fails the entire run — status failed, an error event on the wire, and an error message naming the stage it refused to start. That part is strict and good.
The gap is inside a stage. A stage is given an abort reason it may consult between turns, but only the debate and review-loop modes ever consult it; single and parallel run their turns to completion. So a stage that has already spent past the ceiling will keep taking turns until it finishes. The overshoot is bounded by one stage rather than by one turn, and a parallel stage is the widest case because several employees run at the configured concurrency. Known gaps states this as the real behaviour rather than leaving it to be discovered.
The soft gate is a different shape. DEV3D_SOFT_SPEND_APPROVAL_USD defaults to 1.50, and once a run's spend has crossed it the engine asks a human, exactly once per run, only between stages. The approval is attributed to the first stage's owner and carries no turn id. A refusal cancels the run — it does not pause it. That distinction is worth holding on to: the run status union declares paused and no code path ever sets it, so the one status that would describe pausing is unreachable. Setting the value to 0 disables the gate entirely. In mock mode you will never see it, because scripted turns cost nothing.
DEV3D_RUN_BUDGET_USD does not do what its name says. The variable is read into configuration with a default of 5 and then referenced nowhere else in the source — only the field declaration and the line that reads the environment mention it. .env.example describes it as a hard ceiling that halts a run which would exceed it, and that is not true of the code. The limit that governs is the floor's budget.defaultRunUsd, which is also 5 unless you change it, so the confusion is easy to miss: setting the environment variable changes nothing, and setting the budget in the floor's settings changes everything. Environment marks the variable as unused.
Two smaller gates belong on this list because they are the other places a run can stop and wait. An approval for a shell command sets the stage status to awaiting-approval and the employee's status to blocked, and nothing moves until a human decides; a decision that never comes counts as refused after DEV3D_APPROVAL_TIMEOUT_MS, which is ten minutes by default. And a turn that hits its output cap mid-turn stops, keeping whatever it produced, and is recorded as a failed turn rather than a clean one — it used to keep the status done, which made a truncated work product look finished everywhere except the turn's own error field. If you automate on run status, read each turn's error as well.
What do I need installed?
What are the real prerequisites? Node 24 or newer is a hard floor, and pnpm at the version the repository pins. There is no database server, no build step required to run the orchestrator, and no API key required to see it work.
Why
Each of those three is a floor for a stated reason rather than a preference. Node 24 is required because the test suites execute TypeScript directly through the built-in test runner, and because persistence is built on the unflagged node:sqlite module — both are Node 24 features, and both fail loudly or degrade silently on older runtimes. The worst case is specific and worth naming: on an older Node the orchestrator may still start, which means running a build whose suites cannot run at all.
For the package manager, read the field rather than the folklore: the root manifest declares "packageManager": "pnpm@11.22.0" and there is no engines.pnpm. The pin itself is the floor, enforced through corepack, so corepack enable is the reliable way to get the right version. The repository ships a lockfile in that format, which is the practical reason to match it.
What you do not need is worth as much space. There is no database server to provision: persistence is one SQLite file. There is no build step to run the orchestrator — a Vite build is only needed if you want the orchestrator to serve the UI itself rather than running the dev server. There is no container, no message broker, no queue. And there are no keys: with none configured the office boots in mock mode and runs the entire pipeline with scripted employees. One further requirement is easy to forget because it is about permissions rather than software: the data directory must be writable. If it is not, the store falls back to memory, says so in a warning, and your history disappears on exit.
Does it work on Windows, macOS and Linux?
Is dev3d Linux-only? No. It is plain Node plus a browser, and all three platforms are supported — the repository carries Windows-specific handling rather than treating it as an afterthought, and the shipped documentation quotes Windows commands alongside POSIX ones.
Why
Nothing in the stack is platform-bound. The orchestrator is Node; the console is a browser application; persistence is SQLite through Node's own module rather than a native driver that would need compiling per platform. The path resolver even accounts for Windows syntax explicitly, rejecting drive-relative forms such as C:foo alongside ordinary parent-directory escapes, and it compares case-insensitively — so the workspace boundary behaves the same way on a case-insensitive filesystem as on a case-sensitive one.
The repository has real Windows affordances rather than a disclaimer. The asset tooling documents how the path to Blender is resolved on Windows, with environment variables for the executable or its directory and the default install locations as a fallback, and the screenshot tooling avoids the two traps that make native commands misbehave in PowerShell — piping a native command's output, and reusing a browser profile. Those are small things, and they are the difference between "it probably works" and "somebody ran it".
The one platform-shaped detail that is genuinely worth knowing is not about the operating system at all: the orchestrator has no authentication and is intended for the loopback interface. That is true on every platform, and it is the constraint that decides whether you can point a colleague's browser at your machine. Installation covers the bind address and the environment variables that matter on a first boot.
How much disk does it use?
How big is a dev3d installation? The dependencies dominate, not the office: the JavaScript dependency tree is on the order of a hundred megabytes of files. The application's own data is small — one SQLite file plus a handful of JSON caches — and your workspaces are whatever your projects are.
Why
Break the footprint into three parts and each has a different answer. The dependency tree is the big one, because the console brings a 3D engine and a UI framework with it; measured on a working checkout, the installed modules came to roughly 100 MB of files, and a package store roughly the same again. That is a normal size for a modern JavaScript application and it is the price of the office being three.js rather than a static image.
The application's own state is deliberately small. Persistence is a single SQLite file at the configured database path, and the four caches — model discovery, pooled quality, benchmarks and endpoint health — are JSON documents under the data directory with their own freshness windows. Everything under that data directory is disposable except the database: delete a cache and you pay a network round trip on the next boot; delete the database and you lose your history.
Workspaces are the part you control, and they are ordinary directories. A run reads and writes real files inside its project directory, so a project's disk cost is your project's disk cost. One thing to plan for rather than discover: the database path cannot be changed from the interface afterwards, because the path has to be known before the database can be opened. Choose it deliberately on the first boot — Installation lists exactly which values the environment owns on that boot and which ones it hands over to saved settings from then on.
Does it work offline?
Can I run dev3d with the network unplugged? The orchestrator, the console and the mock provider all work with no network. What needs a connection is anything that reaches a vendor, which in practice means live model calls, first-time model discovery, and the two optional quality indices.
Why
The useful way to think about it is that nothing in dev3d phones home. There is no telemetry, no account and no update check; the only repeating timers in the whole project are a clock in the interface and a keepalive on the socket. A marketplace is contacted only when an operator registered one and asked, and a source that cannot be reached is recorded with its last error and skipped rather than retried in a loop.
The pieces that do reach the network all have a defined offline behaviour, which is the part worth checking rather than assuming. Model discovery caches its results to a JSON file with a six-hour freshness window, so a restart inside that window does not re-ask; if the cache is stale and the provider is unreachable, the provider falls back to the curated table and the console reports the provenance as degraded rather than claiming success. The benchmark source and the pooled quality index are each behind a cache with its own TTL and an off switch, and the pooled index makes no request at all unless a key is configured for it. Endpoint health, which feeds the router's reliability penalty, is cached for ten minutes — and because an unmeasured provider contributes nothing to that term rather than a penalty, an offline office does not silently demote every model it cannot measure.
What genuinely requires a connection is a live turn: an HTTPS request to a vendor. There is no offline mode for that, and no local fallback. The two configurations that satisfy an air-gapped or metered environment are mock mode, which is deterministic and costs nothing, and a local runtime on the loopback interface. Both are described above, and Environment lists every cache path and its TTL for the case where you want to tune the freshness windows.
What happens when a provider is down?
What does dev3d do if my model vendor has an outage? Two things at once: the router demotes models whose upstream endpoints are measured as unhealthy, and each turn carries an ordered list of fallbacks it tries before giving up. When everything fails, the turn fails with a message listing every route it attempted, rather than reporting success.
Why
The scoring half is a penalty rather than an exclusion, and that is deliberate. Measured uptime reduces a model's score by up to 0.30 at worst — comparable to a tier step and a half, which is the right order of magnitude for "this will probably fail" — and by 0.003 at 99% uptime, which is noise. It is not a hard filter because uptime is a rolling measurement that can be stale, and excluding a model on a stale reading would remove a good option from a role pinned to it with no way back. A model nobody has measured contributes exactly zero to the term, so nothing is penalised for being unmeasured.
The fallback half is what actually rescues a turn. Each routing decision produces an ordered fallback list: first the best same-tier model on a different provider, then, if there is room, one model a tier up. The registry tries the chosen route and then each fallback in order, and which one answered is recorded on the turn as servedBy, with every failed attempt kept as an attemptedRoutes entry shaped as the provider, the model and the error. That attribution matters more than it looks: the quality layer records a fallback-served turn as a failure for the model that did not answer, and as evidence about the health of the one that did, rather than crediting the routed model for work it never did.
When nothing answers, the error is explicit rather than generic — the registry throws with the attempted routes joined into one string, so a turn's failure names every provider and model it tried and the error each returned. A user-initiated cancellation is the one exception: an aborted request is re-thrown rather than routed around, because a cancelled turn is not a transport failure.
No test suite exercises a live provider. Every run in the evidence behind this documentation is scripted, and the provider-facing tests inject their own fetch implementation. The decision logic is well covered; real latency, real refusals, real rate limiting and real context limits are unexercised by the suites. That does not mean the failover path is wrong — it means the wire to a vendor is the part you should watch yourself the first time you run it against real keys. Verification says exactly what each suite cannot prove.
Still unanswered?
- Contact — a cost, provider or platform question this page did not answer.
- Documentation — the whole manual, grouped by section.
- Installation — every provider key, what
autoreally means, and the first-boot precedence rules. - Environment — every variable, its real default, and which ones are unused.
- Model routing — how a turn gets its model, and what the postures actually change.
- Known gaps — the budget, confinement and degradation limits stated in full.
Where to go next
- Frequently asked questionsSection
Short answers to the questions people arrive with, each one linked to the page that goes deeper.
- How a run flowsConcept
The real record hierarchy, twelve stage kinds, four stage modes, budgets and failure policy.
- Known gapsConcept
What is unfinished, what is a deliberate trade, and what the platform will not allow.
Linked from
Did this page answer your question?