Serve a model in three commands

The engine is one program, veymeer. It serves GGUF models over an OpenAI-compatible API on your machine. This page covers what most people need; the operator's guide that ships with the engine covers every setting.

Quick start

Check the machine, see which models are on it, and serve one. Models that Ollama already downloaded are found where they are.

veymeer doctor                       # what this machine offers, and anything in the way
veymeer models                       # the models on this machine
veymeer serve --model qwen2.5:7b     # serve one at http://127.0.0.1:8080/v1

Any OpenAI client works against it. Nothing about the client changes except the address.

Python
from openai import OpenAI

client = OpenAI(base_url="http://127.0.0.1:8080/v1", api_key="not-needed-locally")

stream = client.chat.completions.create(
    model="qwen2.5:7b",
    messages=[{"role": "user", "content": "Explain what a mutex is."}],
    stream=True,
)
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")
curl
curl http://127.0.0.1:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen2.5:7b", "messages": [{"role": "user", "content": "Hello"}]}'

Or skip the server and talk to a model in the terminal:

veymeer chat --model qwen2.5:7b

The command line

Every command takes --help.

veymeer

The output of the engine on our test machine, replayed. Yours will name your own hardware.

CommandWhat it does
veymeer setupInstall the engine on this machine: into place, onto the PATH, into the list of installed programs. --system for every user, --remove to take it out, --status to see what is installed.
veymeer doctorCheck the processor, the GPUs, the models, the data folder, the port and the licence. Exits non-zero if something would stop the engine from serving.
veymeer pull owner/repo[:QUANT]Download a model from the Hugging Face Hub. Resumes, and checks the file against the Hub's checksum. --list shows the repository's files.
veymeer models, rmThe models on this machine and whether the engine runs them; remove one.
veymeer serveServe the API.
veymeer chat, run "prompt"Talk to a model in the terminal. If an engine is already serving, it answers; otherwise the model is loaded for the command.
veymeer statusWhat the engine running on this machine is serving, on what, and under which tier.
veymeer settingsThe running engine's settings; settings set name=value changes them, --persist keeps the change.
veymeer benchMeasure a model here: three kinds of work, time to read the prompt and tokens a second.
veymeer login, logoutSign in with a VEYMEER account through the browser to use its plan on this device; sign out.
veymeer licenseWho is signed in and the tier in force.
veymeer service installRun as a system service. Also start, stop, status, uninstall.
veymeer nodeLend this machine's devices to a cluster.
veymeer devices, paths, configWhat the machine offers; where this installation keeps models, data and settings; the settings serve would run with.

The API

OpenAI's routes and fields, plus a few of the engine's own. Streaming uses server-sent events and ends with data: [DONE]. Errors are JSON with the usual status codes.

Route
POST /v1/chat/completionsChat. Sampling controls, penalties, seed, stop, stream, logprobs, response_format, tools.
POST /v1/completionsRaw text completion, with the same options and json_schema, grammar, regex.
GET /v1/modelsThe model being served; every installed model when model switching is on.
POST /tokenizeToken count of a prompt or chat, and the room left for the answer.
POST /primeRead a prompt or chat ahead of the question.
GET, PATCH /v1/settingsThe settings in force, and changing them while the server runs.
GET /healthModel, device, settings, tier and the last request's speed.
GET /livez, /readyz, /metricsProbes and Prometheus metrics.

Reading ahead

The first word of an answer waits for the prompt to be read. An application that knows the beginning of a prompt before the question exists, such as an open file or a long instruction, can send it ahead. The request that follows only reads what is new.

curl http://127.0.0.1:8080/prime \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "system", "content": "...a long instruction..."}]}'
# {"tokens": 1840, "read": true}

Per-request switches

Each response carries a veymeer object with the speed it was written at. A request can turn features off for itself in its own veymeer object: "remember": false, "ahead": false, "draft": false, "speculate": false. None of them changes the answer.

Structured output and tools

An answer can be held to a form, and then it always has that form.

Request fieldThe answer is
"response_format": {"type": "json_object"}a JSON object
"response_format": {"type": "json_schema", ...}JSON that fits the schema, as OpenAI's structured outputs
"grammar": "root ::= ..."text the GBNF grammar accepts
"regex": "[0-9]{4}-[0-9]{2}"text the regular expression matches
"tools": [...]a reply, or tool_calls whose arguments fit each function's schema
curl http://127.0.0.1:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen2.5:7b",
    "messages": [{"role": "user", "content": "Invoice 1042, 3 items, 59.90 EUR, due 2026-11-01"}],
    "response_format": {"type": "json_schema", "json_schema": {"strict": true, "schema": {
      "type": "object",
      "properties": {
        "number": {"type": "integer"},
        "total":  {"type": "number"},
        "due":    {"type": "string", "format": "date"}
      },
      "required": ["number", "total", "due"]
    }}}
  }'

Give max_tokens room: an answer that runs out of tokens before its form is complete ends with finish_reason: "length". A schema keyword that cannot be enforced is refused when strict is set, instead of being ignored.

Settings

Every setting can be given in a settings file, as an environment variable (VEYMEER_<SETTING>) or as a flag (--<setting>), later ones overriding earlier ones. veymeer config prints the settings a serve would run with.

SettingDefaultMeaning
modelqwen2.5:7bModel name, or the path of a .gguf file
ctx0Context length in tokens. 0 sizes it when the model loads: as long as the model was trained for, as far as the machine holds it beside the whole model
backendautoauto, cuda, webgpu or cpu
precisionhighhigh is exact; balanced and fast trade a little for memory and prompt-reading speed
draft_modelautoA small model that writes ahead: picked automatically, named, or off
kv8falseKeep conversations in 8 bits on NVIDIA GPUs: about twice the context in the same memory, at a small loss of precision. Built, not yet measured
speculationtrueGuess ahead and check several tokens a pass; false writes one at a time, with the same answers
memory_mb256Memory for answers already given; 0 turns it off
ahead3While idle, prepare for this many likely follow-up questions; 0 turns it off
model_switchfalseServe whichever installed model a request names
max_sessions16Conversations answered at once, up to what the tier serves
host, port127.0.0.1, 8080Where to listen
api_keysnoneKeys clients must send; required to listen beyond this machine

Changing settings while it runs

A running server takes changes over its API, or from the command line. A change that needs the engine rebuilt lets running answers finish, queues new ones, and is rolled back if the engine does not start with it. Web pages cannot change settings, since any site you open could send requests to your machine: only programs, pages served from this machine, and sites named in cors_origins can.

veymeer settings set ctx=8192 precision=fast --persist

curl -X PATCH http://127.0.0.1:8080/v1/settings \
  -d '{"model": "llama3.1:8b", "draft_model": "off"}'

Models

A model is named the way Ollama names it (qwen2.5:7b) or by the path of a .gguf file. Named models are looked up in the models folder: --models-dir, else $OLLAMA_MODELS, else Ollama's own folder. veymeer models lists every model found and says ok or why it cannot run.

ArchitecturesLlama 1 to 3.x, Mistral, Mistral Nemo, Mixtral, Qwen2 and 2.5, Qwen2-MoE, Qwen3, Qwen3-MoE, Gemma 1 to 3, Gemma 4 (E2B, E4B), Phi-2, Phi-3 and 3.5, gpt-oss, GPT-2, StarCoder 1 and 2, Falcon, GPT-NeoX (Pythia), StableLM, MPT, BLOOM, OLMo 1 and 2, OLMoE, Command-R, Cohere2, Granite, Granite-MoE, MiniCPM, InternLM2, EXAONE, Orion, Nemotron, Arcee, SmolLM3, GLM-4, ERNIE 4.5, Hunyuan, DeepSeek MoE, XVERSE: on the processor and through WebGPU, checked against each other; on NVIDIA GPUs, measured for Llama, Qwen, Mistral and Gemma 4 and built, not yet measured, for the rest. Find a model
QuantisationsF32, F16, BF16, Q2_K, Q3_K, Q4_0, Q4_1, Q4_K, Q5_0, Q5_1, Q5_K, Q6_K, Q8_0, IQ1_S, IQ1_M, IQ2_XXS, IQ2_XS, IQ2_S, IQ3_XXS, IQ3_S, IQ4_NL, IQ4_XS, MXFP4, TQ1_0, TQ2_0 (IQ1 to IQ3 on the processor and NVIDIA GPUs)
Chat formatsChatML, Llama 3, Mistral, Gemma, Gemma 4, Phi, harmony (gpt-oss)
ToolsIn every chat format: offered in the model's own template, read back as OpenAI's tool_calls

A draft model has to share the large model's vocabulary: a small model of the same family, such as Qwen2.5 0.5B for Qwen2.5 7B, or Llama 3.2 1B for Llama 3.1 8B. The engine refuses a pair that does not match.

Signing in

The Individual tier needs no account. Signing in brings a paid plan to a device.

veymeer login      # opens the browser; sign in there and approve this device
veymeer license    # who is signed in, and the tier in force
veymeer logout     # sign this device out

The engine prints a short code and opens the device page of this site. You sign in there, with your second factor if the account has one, and approve the device. The engine then holds a licence for that device and renews it by itself while it serves. A machine without a browser can use veymeer login --no-browser and approve from any other device.

The first time the engine is run at a terminal it asks whether to continue without an account or to sign in. A program that runs the engine for you, such as an editor, a service or a script, is never asked.

Without a network. A licence can also be installed as a file: veymeer license install <file>. The engine checks its signature itself and needs no connection to do so.

Clusters

One model can run across machines on the same network.

# on every machine that lends its hardware
veymeer node --beacon

# on the machine that serves
veymeer serve --model llama3.1:8b --discover --cluster-key KEY
# or name the nodes
veymeer serve --model llama3.1:8b --nodes KEY@192.168.1.20,KEY@192.168.1.21

Connections are encrypted and both ends must hold the join key. Treat the key like a password. How many other machines a cluster may have depends on the tier; what we have and have not measured is on the hardware page.

What the engine sends

Serving a model, the engine talks only to the clients that call it, and to the machines of a cluster if you set one up. Beyond that it makes a network request of its own in three cases, each of which you start or can see:

WhenToWhat
veymeer pullThe Hugging Face HubThe download request for the model you named
veymeer login, and renewal while signed inThe account serverAn identifier for the installation, the machine's name, the engine's version, the operating system
Once a day while serving, in a release that names an account serverThe account serverThe engine's version, to fetch the notice of when the launch period ends

The identifier is a one-way hash of the operating system's installation id. It is stable for an installation and means nothing anywhere else; no hardware address is read or sent. The engine never sends your models, your prompts, your answers, or how much you use it.

Troubleshooting

SymptomWhat to check
The model is not foundveymeer models and the models folder (veymeer paths)
It starts on the processor although there is a GPUveymeer devices; the log says why each faster device was passed over
"the weights of some layers stay in host memory"The model is larger than the GPU memory available. Lower ctx, close other GPU programs, or accept the slower writing
429 responsesMore requests than the engine serves and queues at once
A structured answer ends with "length"max_tokens ran out before the form was complete: raise it
The first start is slower than later onesThe engine measures the GPU once and remembers the result

Everything else is in the operator's guide

Every setting, the service, TLS, logging and monitoring are described in the guide that ships beside the engine.