Skip to main content
The Buttress server reads a single TOML file passed via --config. Every section is optional; omit it to use defaults.

Minimal example

[server]
port = 2080

[[generators]]
type = "ggml-llm"
[generators.model]
repo_id = "ggml-org/gpt-oss-20b-GGUF"
quantization = "mxfp4"
n_ctx = 12800

Top-level sections

SectionPurpose
[env]Environment variables exported into the process only if not already set
[server]HTTP/WebSocket listener (port, log level, body limits)
[runtime]Global defaults shared by every generator
[runtime.session_cache]KV-cache reuse store for ggml-llm
[autodiscover]LAN UDP / HTTP discovery toggles
[openai_compat]Enable OpenAI-compatible HTTP routes
[anthropic_messages]Enable Anthropic-compatible HTTP routes
[[generators]]Array of generator instances — one entry per loaded model

[server]

KeyTypeDefaultDescription
idstringbuttress-<machineId>Stable server id used for binding and discovery
namestringButtress Server (<short id>)Friendly name shown in BRICKS Controller
portnumber2080HTTP/WebSocket port (overridden by --port)
log_levelstringunsetOne of debug, info, warn, error
max_body_sizenumber or string"50MB"Max upload size; accepts "100MB", "1GB", or raw bytes
session_timeoutnumber or string60000WebSocket idle timeout in ms; also accepts "1m", "30s"
temp_file_dirstring$TMPDIR/.buttressDirectory for STT audio uploads and other temp files

[runtime]

Global defaults shared by every generator. Per-generator values under [generators.model] win; otherwise these defaults apply.
[runtime]
cache_dir = "~/.buttress/models"
huggingface_token = "hf_..."
n_gpu_layers = "auto"
KeyTypeDescription
cache_dirstringModel and metadata cache root (default ~/.buttress/models)
huggingface_tokenstringHugging Face auth token; falls back to $HUGGINGFACE_TOKEN. Applied to all backends regardless of variable name
http_headerstableExtra headers attached to Hugging Face / HTTP downloads
context_release_delay_msnumberIdle time before unloading a context (default 10000; 0 = immediate)
prefer_variantsstring[]Override backend variant probe order (ggml backends)
n_threadsnumberCPU thread count
n_ctxnumberContext window (per-model value wins; auto-capped at training context)
n_gpu_layersnumber or "auto"Layers offloaded to GPU (default "auto")
n_batchnumberPrompt batch size. Note: the model layer defaults n_batch to 512, which shadows the runtime value unless n_batch is set explicitly under [generators.model]
n_ubatchnumberPrompt micro-batch size
n_parallelnumberParallel sequences (default 4)
n_cpu_moenumberMoE expert layers offloaded to CPU
flash_attn_typestring"on", "off", or "auto". Default is GPU-conditional: "auto" when a GPU backend is selected, "off" on CPU
cache_type_k, cache_type_vstringKV-cache dtype (f16, f32, q8_0, q4_0, …)
kv_unifiedbooleanUse a unified KV cache across sequences
swa_fullbooleanMaterialize full attention even for sliding-window layers
ctx_shiftbooleanAllow llama.cpp’s rolling context shift
use_mmap, use_mlockbooleanMemory-mapping / locking
no_extra_buftsbooleanDisable extra compute buffer types
cpu_mask, cpu_strictstring / booleanCPU affinity (advanced)
devicesstring[]Restrict to specific GGML devices
Speculative keysvariousspeculative, spec_type, spec_draft_n_max, spec_draft_n_min, spec_draft_p_min, spec_draft_p_split

[runtime.session_cache]

For ggml-llm generators, the server can persist KV cache state between requests so that a follow-up completion sharing a prompt prefix skips prompt processing.
[runtime.session_cache]
enabled = true
max_size_bytes = "10GB"
max_entries = 1000
KeyDefaultDescription
enabledtrueEnable persistent KV cache
max_size_bytes"10GB"Total disk budget; accepts "500MB", "50GB", or a number
max_entries1000Max number of cached states (LRU eviction)
Cache files are stored under {cache_dir}/.session-state-cache/. mlx-llm keeps a separate session cache under {cache_dir}/mlx-session-cache/, configured independently per generator.

[[generators]]

Each [[generators]] block declares one model the server can host. Repeat the block to host multiple. Every block has a type, an optional [generators.backend] table, and a [generators.model] table.
[[generators]]
type = "ggml-llm"

[generators.backend]
# backend selection and resource planning

[generators.model]
repo_id = "..."
# model identity and runtime overrides

Common [generators.model] keys

Shared by all generator types (ggml-llm, ggml-stt, mlx-llm):
KeyTypeDescription
repo_id (required)stringHugging Face repo (org/repo)
revisionstringDefault "main"
downloadbooleanPre-download at server startup (default false)
Honored by ggml-llm and ggml-stt only (mlx-llm derives quantization from the repo itself and ignores these):
KeyTypeDescription
filenamestringPin a specific artifact in the repo
urlstringDirect download URL (skips manifest lookup)
quantizationstringPreferred quant tag — e.g. q4_0, q8_0, mxfp4
preferred_quantizationsstring[]Ordered fallback list when quantization doesn’t match (alias: quantizations)
allow_local_filebooleanRequired to use local_path or mmproj_local_path
local_pathstringUse a local file as the load path. Repo metadata is still resolved from Hugging Face, so repo_id is still required
api_base, base_urlstringOverride Hugging Face API / blob hosts (mirrors or proxies)

ggml-llm (llama.cpp / GGUF)

[[generators]]
type = "ggml-llm"

[generators.backend]
variant_preference = ["cuda", "vulkan", "default"]
gpu_memory_fraction = 0.95

[generators.model]
repo_id = "ggml-org/gpt-oss-20b-GGUF"
quantization = "mxfp4"
n_ctx = 12800
download = true
[generators.backend] only controls backend selection and resource planning. Runtime overrides (n_ctx, n_gpu_layers, flash_attn_type, etc.) go under [generators.model]. [generators.backend]
KeyTypeDefaultDescription
variantstringautoForce cuda, vulkan, snapdragon, or default
variant_preferencestring[]["cuda", "vulkan", "snapdragon", "default"]Probe order when variant is unset
gpu_memory_fractionnumber0.85Max GPU fraction the hardware guardrails may plan against
cpu_memory_fractionnumber0.5Max RAM fraction for CPU-side buffers
[generators.model] — in addition to the common ggml keys above, every [runtime] key can be overridden per-generator: n_ctx, n_gpu_layers, n_batch, n_ubatch, n_threads, n_parallel, n_cpu_moe, flash_attn_type, cache_type_k, cache_type_v, kv_unified, swa_full, ctx_shift, use_mmap, use_mlock, no_extra_bufts, cpu_mask, cpu_strict, devices. Multimodal (mtmd) — auto-downloads the matching mmproj-*.gguf from the same repo:
KeyTypeDescription
enable_mtmdbooleanDefault false
mmproj_filenamestringPin a specific projector file
mmproj_urlstringDirect URL override
mmproj_local_pathstringLocal projector file (requires allow_local_file = true)
mmproj_use_gpubooleanUnset = auto (true when n_gpu_layers > 0)
mmproj_image_min_tokensnumberMin visual tokens (dynamic-resolution models; -1 = unset)
mmproj_image_max_tokensnumberMax visual tokens (-1 = unset)
Speculative decoding
KeyTypeDescription
speculativestringDraft model identifier
spec_typestringStrategy (backend-defined)
spec_draft_n_maxintMax drafted tokens per step
spec_draft_n_minintMin drafted tokens
spec_draft_p_minnumberMin acceptance probability
spec_draft_p_splitnumberSplit threshold

ggml-stt (whisper.cpp)

[[generators]]
type = "ggml-stt"

[generators.backend]
variant_preference = ["cuda", "vulkan", "default"]

[generators.model]
repo_id = "BricksDisplay/whisper-ggml"
filename = "ggml-large-v3-turbo-q8_0.bin"
use_gpu = true
use_flash_attn = "on"
download = true
[generators.backend]
KeyTypeDefaultDescription
variantstringautoForce cuda, vulkan, or default
variant_preferencestring[]["cuda", "vulkan", "default"]Probe order
gpu_memory_fractionnumber0.85
cpu_memory_fractionnumber0.5
[generators.model] — in addition to the common ggml keys above:
KeyTypeDefaultDescription
repo_idstring"BricksDisplay/whisper-ggml"Defaulted (unlike ggml-llm)
preferred_quantizationsstring[]["q8_0", <no-quant>, "q5_1"]Default fallback chain
use_gpubooleantrueSet to false to force CPU even when a GPU is available
use_flash_attnstring or boolean"auto""on", "off", or "auto". true / false are accepted as shortcuts. "auto" enables flash-attn when a GPU is in use
Runtime extras — under [runtime] for ggml-stt only:
KeyTypeDescription
max_threadsnumberCaps the whisper.cpp thread count

mlx-llm (Apple Silicon)

[[generators]]
type = "mlx-llm"

[generators.model]
repo_id = "mlx-community/Qwen2.5-VL-3B-Instruct-4bit"
vlm = true
download = true
There is no [generators.backend] section for mlx-llm. On first use, the backend creates a Python virtualenv at {cache_dir}/mlx-env and installs mlx_lm_package, mlx_vlm_package, plus torch and torchvision (required by some VLM processors). If an existing venv already has mlx_vlm and torch importable, the install step is skipped. [generators.model] — common repo_id / revision / download plus:
KeyTypeDefaultDescription
adapter_pathstringLocal LoRA adapter directory
vlm"auto" or boolean"auto"Force VLM (true) vs text-only (false); "auto" infers from the repo
tokenizer_configtableForwarded to mlx_lm.load(..., tokenizer_config=...)
model_configtableForwarded to mlx_lm.load(..., model_config=...)
quantization, filename, and preferred_quantizations are not used — the MLX repo itself determines the quantization. Runtime extras — under [runtime] for mlx-llm:
KeyTypeDefaultDescription
mlx_env_dirstring{cache_dir}/mlx-envLocation of the auto-managed Python venv
mlx_lm_packagestring"mlx-lm==0.31.1"pip spec used when provisioning the venv
mlx_vlm_packagestring"mlx-vlm==0.4.0"pip spec used when provisioning the venv

[autodiscover]

The server announces itself on UDP 8089 so Foundation devices on the same LAN can find it. Auto-discovery is on by default.
[autodiscover]
[autodiscover.udp]
port = 8089

[autodiscover.udp.announcements]
enabled = true
interval = 5000

[autodiscover.udp.requests]
enabled = true
responseDelay = 100

[autodiscover.http]
enabled = true
path = "/buttress/info"
cors = true
Set autodiscover = false to disable discovery entirely. See the autodiscovery reference for protocol details.

[env]

Environment variables applied at startup, but only if they are not already set in the system environment. System variables and command-line exports take precedence.
[env]
HUGGINGFACE_TOKEN = "hf_..."
CUDA_VISIBLE_DEVICES = "0"
The ggml backends read HUGGINGFACE_TOKEN (not HF_TOKEN). For a single token that applies to every backend regardless of variable name, set [runtime] huggingface_token instead.

Compatibility endpoints

These endpoints are experimental. The schemas, error shapes, and CORS defaults may change.
The server can expose OpenAI- and Anthropic-compatible HTTP routes alongside the native WebSocket RPC. Each is opt-in.
[openai_compat]
enabled = true
# cors_allowed_origins = "*"

[anthropic_messages]
enabled = true
# cors_allowed_origins = ["http://localhost:3000"]
EndpointConfig flag
POST /oai-compat/v1/chat/completions[openai_compat] enabled = true
GET /oai-compat/v1/models[openai_compat] enabled = true
POST /anthropic-messages/v1/messages[anthropic_messages] enabled = true
POST /anthropic-messages/v1/messages/count_tokens[anthropic_messages] enabled = true
You can also enable each endpoint via env var: ENABLE_OPENAI_COMPAT_ENDPOINT=1 or ENABLE_ANTHROPIC_MESSAGES_ENDPOINT=1.

Next steps

Workspace binding

Pair the server with a BRICKS workspace and enable auth.

LAN auto-discovery

How Foundation devices find your server on the LAN.