Skip to content

Configuration

mlxcel is configured through a combination of environment variables (which affect all invocations) and command-line flags (which override environment variables for a specific run). This page documents the environment variables that control device selection and memory management, as well as the server-specific configuration options.

Table of Contents


Environment Variables

These variables are read at startup and apply to both the generate command and the serve command.

Variable Description Default
MLXCEL_DEVICE Force the runtime device. Accepted values: gpu, metal, cpu. Auto (GPU if available)
MLXCEL_WIRED_LIMIT GPU wired memory limit. See Memory Management for format details. max GPU memory
MLXCEL_MEMORY_LIMIT Soft MLX allocator memory cap. Also feeds mlxcel inspect and --estimate-memory as the authoritative available-memory figure when nonzero. Unset
MLXCEL_HEADROOM_FACTOR Runtime/activation headroom multiplier used by the unified memory estimator. Positive values <= 1.0 disable the headroom term; invalid or non-positive values warn and fall back to the default. 1.20
MLXCEL_CACHE_DIR Root for the default model store ($MLXCEL_CACHE_DIR/models/<owner>/<name>) and other mlxcel disk caches. $HOME/.cache/mlxcel
MLXCEL_MODELS_DIR Override the model-store root directly. Repo-id downloads and lookups use $MLXCEL_MODELS_DIR/<owner>/<name> with no extra models/ component. Unset
MLXCEL_DEFAULT_ORG Default HuggingFace owner for bare model names with no slash. mlx-community
MLXCEL_WEIGHT_MATERIALIZATION eager reads and uploads a generation model's checkpoint tensors before Model loaded is reported, so the first token pays no weight I/O. lazy materializes each tensor on first use. eager
MLXCEL_EXTRA_CA_CERTS PEM bundle (at most 1 MiB) of extra root or intermediate CAs trusted for model downloads and remote media fetches, on top of the operating system trust store. Needed behind a TLS-inspecting proxy whose root CA the system store lacks. Unset
CUDA_HOME Path to the CUDA Toolkit installation directory (Linux only, build-time). /usr/local/cuda
MLX_CUDA_ARCHITECTURES Target GPU SM version(s) for CUDA kernel compilation (Linux only, build-time). Auto-detected via nvidia-smi
LLAMA_ARG_MODEL Default model path (used by mlxcel serve and mlxcel-server). None
LLAMA_ARG_HOST Default server host binding address. 127.0.0.1
LLAMA_ARG_PORT Default server port. 8080
LLAMA_API_KEY API key for server authentication. None
LLAMA_ARG_CTX_SIZE Default context window size for the server. 0 (model default)
LLAMA_ARG_N_PARALLEL Default number of parallel request slots. 4
LLAMA_ARG_N_PREDICT Default maximum tokens per generation. The -1 sentinel resolves to the effective per-slot context window. -1
LLAMA_ARG_TIMEOUT HTTP socket read/write timeout in seconds. Does not cancel a slow generation. 3600
MLXCEL_DECODE_TIMEOUT Per-request decode watchdog in seconds: cancels a request whose generation stops producing tokens. 600
LLAMA_ARG_SPEC_DRAFT_N_MAX The --draft-max value. LLAMA_ARG_DRAFT_MAX is read when this one is unset. The server reports it as n_max in /props; the proposal width comes from LLAMA_ARG_DRAFT_BLOCK_SIZE. 16
LLAMA_ARG_MODEL_DRAFT Drafter checkpoint path for the standalone mlxcel-server binary. None
LLAMA_ARG_DRAFT_KIND Drafter kind override: dflash, mtp, full-model, or prompt-lookup. MLXCEL_DRAFT_KIND is the mlxcel-native alias. Auto-detect
LLAMA_ARG_DRAFT_BLOCK_SIZE Draft block size for DFlash, MTP, full-model, and prompt-lookup. MLXCEL_DRAFT_BLOCK_SIZE is the mlxcel-native alias. Resolved at startup from the drafter, device, and target quantization
LLAMA_ARG_CACHE_REUSE llama.cpp-compatible alias for prompt-cache enablement. See MLXCEL_PROMPT_CACHE_ENABLED
MLXCEL_PROMPT_CACHE_ENABLED Enable prompt-prefix KV cache. Accepts true/false, 1/0, on/off. true
MLXCEL_PROMPT_CACHE_CAPACITY_BYTES Prompt-cache byte budget. 2147483648
MLXCEL_PROMPT_CACHE_MAX_ENTRIES Prompt-cache entry cap. 1024
MLXCEL_PROMPT_CACHE_TTL Prompt-cache TTL in seconds. 3600
MLXCEL_PROMPT_CACHE_MIN_PREFIX Minimum token prefix length eligible for caching. 32
APC_ENABLED Automatic Prefix Caching block-hash layer. true
APC_BLOCK_SIZE Tokens per APC block. 16
APC_NUM_BLOCKS APC entry cap. Derived
APC_HASH APC hash algorithm: sha256 or blake3. sha256
MLXCEL_AUDIO_QUEUE_DEPTH Waiting commands in the audio worker queue. 8
MLXCEL_AUDIO_REQUEST_TIMEOUT_SECS Audio worker reply timeout. 120
LLAMA_ARG_RESPONSES_STORE_MAX_ENTRIES Maximum stored /v1/responses objects. 1024
LLAMA_ARG_RESPONSES_STORE_TTL_SECS /v1/responses store TTL in seconds. 3600
LLAMA_ARG_CONVERSATION_STORE_MAX_ENTRIES Maximum stored Responses API conversation transcripts. 256
LLAMA_ARG_CONVERSATION_STORE_TTL_SECS Conversation transcript TTL in seconds. 3600
MLXCEL_SERVER_DECODE_STORAGE Continuous-batching decode storage backend: auto, dense, or paged. auto
MLXCEL_VIDEO_DIR_ALLOWLIST Comma-separated directory allowlist for local video_url files. Empty means fail-closed. Resolved once at startup for both native-video families and the frames fallback, so restart after changing it or after creating a listed directory. Empty
MLXCEL_REQUEST_MEMORY_BUDGET Per-request memory budget for single-slot Metal Nemotron-H serving. It can only lower the budget derived from the runtime memory caps; an invalid value (zero, none, empty, non-finite, or overflowing) stops startup. Derived from runtime caps
LLAMA_LOG_FILE Path to write server logs. None (stderr)

Note: Variables prefixed with LLAMA_ARG_ are intentional compatibility aliases. They allow mlxcel to be used as a drop-in replacement for llama-server in scripts and deployment configurations that already set these variables.


Device Selection

How Device Selection Works

When mlxcel starts, it selects a compute device in this order:

  1. If MLXCEL_DEVICE is set to cpu, the CPU is used unconditionally.
  2. If MLXCEL_DEVICE is set to gpu or metal, the GPU is used (an error is raised if no GPU is available).
  3. Otherwise, the GPU is used automatically if available, and the CPU is used as a fallback.

On Apple Silicon, the GPU is the Metal-accelerated unified memory device. On Linux, it is the first CUDA-capable GPU (cuda:0). There is currently no multi-GPU round-robin within a single process; multi-GPU support is handled through the distributed inference features.

Forcing CPU Mode

CPU mode is useful for debugging model correctness or running on machines without compatible GPU hardware:

MLXCEL_DEVICE=cpu mlxcel generate -m ./models/my-model -p "Hello"

CPU inference is significantly slower than GPU inference for most models. It is not recommended for production use.


Memory Management

The Wired Memory Concept

On Apple Silicon, MLX uses "wired memory", memory that is pinned and cannot be swapped to disk. Wired memory is critical for performance because GPU operations require memory to be resident. However, over-wiring can cause system instability or OOM (out-of-memory) errors if other applications also need memory.

The MLXCEL_WIRED_LIMIT variable controls how much GPU memory mlxcel is allowed to wire.

Accepted Values

Value Behavior
unset or max Wire up to the GPU maximum at startup. This matches Python mlx-lm's wired-limit context behavior.
0 or none No wired limit. mlxcel does not configure a wired memory ceiling.
96GB, 48GB, etc. Wire up to the specified amount. Supports GB, MB, and bare byte counts.
unlimited Alias for max.

Choosing a Wired Limit

For most users running mlxcel as the primary GPU workload on a dedicated machine, leaving MLXCEL_WIRED_LIMIT unset (the default) is the correct choice: mlxcel sets the wired limit to the GPU maximum, matching the mlx-lm pattern for keeping model weights resident.

If you experience memory pressure from other processes, set an explicit limit:

# Reserve 96 GB for mlxcel on a 128 GB system, leaving 32 GB for the OS and other apps
MLXCEL_WIRED_LIMIT=96GB mlxcel serve -m ./models/my-large-model --port 8080

Important: On Linux (CUDA), MLXCEL_WIRED_LIMIT has no effect. CUDA memory management is handled by the CUDA runtime. Use standard CUDA environment variables (CUDA_VISIBLE_DEVICES, etc.) to control GPU allocation on Linux.


Server Configuration

Server configuration is applied via command-line flags when starting mlxcel serve or mlxcel-server. Many flags also read from environment variables (documented in the table above).

Networking and Authentication

Flag Environment Variable Default Description
--host HOST LLAMA_ARG_HOST 127.0.0.1 Address to bind the HTTP server to. Use 0.0.0.0 to accept connections from all interfaces.
--port PORT LLAMA_ARG_PORT 8080 TCP port to listen on.
--api-key KEY LLAMA_API_KEY None When set, all API endpoints (except /health and /) require Authorization: Bearer <key>.
--api-key-file PATH None None Read the API key from a file (whitespace trimmed). Takes precedence over --api-key.
--timeout SECONDS LLAMA_ARG_TIMEOUT 3600 HTTP socket read/write timeout, matching llama-server b10621. Bounds one socket read or write, not the generation.
--decode-timeout SECONDS MLXCEL_DECODE_TIMEOUT 600 Per-request decode watchdog: cancels a request whose generation stops producing tokens.
--alias NAME LLAMA_ARG_ALIAS None Model alias shown in API responses instead of the directory name.

Example: start the server accessible from the local network, with authentication:

mlxcel serve \
    --model ./models/llama-3.1-8b-4bit \
    --host 0.0.0.0 \
    --port 8080 \
    --api-key my-secret-key

Generation Defaults

These flags set the default sampling parameters applied to requests that do not specify their own values. Per-request parameters always take precedence over these defaults.

Flag Default Description
--ctx-size N 0 (model default) Context budget in tokens. 0 uses the model's configured maximum; an explicit value is shared across active server slots.
--n-predict N -1 Maximum tokens to generate per request. -1 resolves to the effective per-slot context window (or the 4096-token fallback if neither a server nor model limit is available).
--temp FLOAT 0.8 Default sampling temperature. 0.0 is greedy (deterministic).
--top-p FLOAT 0.9 Default nucleus sampling threshold.
--top-k N 40 Default top-K sampling limit. 0 disables top-K filtering.
--min-p FLOAT 0.1 Default min-P sampling threshold. 0.0 disables min-P filtering.
--seed N None Default random seed for reproducible outputs.
--repeat-last-n N 64 Context window size for repetition penalty.
--repeat-penalty FLOAT 1.0 Repetition penalty multiplier. Values above 1.0 discourage repetition.
--frequency-penalty FLOAT 0.0 Frequency penalty subtracts proportionally to how often a token has appeared.
--presence-penalty FLOAT 0.0 Presence penalty subtracts a flat amount for any token that has appeared.
--dry-multiplier FLOAT 0.0 DRY (Don't Repeat Yourself) penalty multiplier. 0.0 disables DRY.
--dry-base FLOAT 1.75 DRY exponential base for scaling the penalty with match length.
--dry-allowed-length N 2 Minimum suffix match length before DRY penalty applies.
--dry-penalty-last-n N -1 DRY lookback window. -1 uses the full context.

Continuous Batching

Continuous batching allows mlxcel to serve multiple concurrent requests efficiently by grouping their decode steps into a single forward pass. This significantly improves throughput under load without increasing latency for individual requests.

Flag Default Description
--n-parallel N, --parallel N 4 Number of parallel request slots. This is the primary control for concurrency and the default divisor for an explicit --ctx-size.
--max-batch-size N Same as --n-parallel Maximum sequences in the active decode batch. When set, this is the divisor for an explicit --ctx-size.
--max-queue-depth N 32 Maximum requests waiting in the prefill queue before new requests are rejected.
--prefill-chunk-size N 2048 idle, 512 with live decode Tokens per prefill chunk. Long prompts are split into chunks of this size, with decode steps interleaved between chunks so active sequences are not starved. When unset, the server uses 2048 while no other sequence is decoding and 512 while a decode batch is live. An explicit value, -b/--batch-size (LLAMA_ARG_BATCH), or MLXCEL_PREFILL_CHUNK pins both states to one size. Set 0 to disable chunking.
--prefill-grant-interval N 16 Guaranteed-prefill fairness interval in decode ticks. Lower values improve TTFT and raise decode ITL; 0 disables the grant.
--max-batch-prefill N 4 Maximum queued requests to combine into one batched prefill pass.
--max-batch-prefill-tokens N derived Padded-token budget for one batched prefill; 0 disables the cap. When unset, it is 2 * max_batch_prefill * min(prefill_chunk_size, 512) (4096 at the defaults).
--enable-preemption Disabled When enabled, a high-priority request can evict a lower-priority active sequence (which is re-queued for re-prefill).
--preemption-policy POLICY longest-first Eviction victim selection. longest-first evicts the sequence with the most generated tokens; lowest-priority evicts the lowest-priority sequence.
--no-batch Disabled Disable the batch scheduler and use legacy sequential processing (one request at a time), preserving the full explicit --ctx-size for that single slot.
--max-kv-size N 0 Cap plain, non-sliding KV caches to N tokens per sequence. 0 leaves them unbounded.
--decode-storage-backend auto\|dense\|paged auto Select the continuous-batching decode storage backend.
--kv-cache-budget BYTES\|auto\|none auto Paged KV block budget (MLXCEL_KV_CACHE_BUDGET). auto derives it from the memory estimate; none or 0 leaves the pool unbounded. Applies only to the paged decode backend.
--kv-admission-watermark FRACTION 0.01 Share of the paged KV block budget, in 0.0..=0.5, that a prefill admission keeps free while rows are decoding (MLXCEL_KV_ADMISSION_WATERMARK). To make that room, admission evicts cold prompt-cache prefixes and, for a higher-priority request, preempts strictly lower-priority rows. A request that fits the budget is never refused. 0 disables it; it has no effect without a block budget.

For llama.cpp compatibility, --ctx-size C is interpreted as a total context budget for the server when C > 0. The effective per-slot context window is floor(C / active_slots), where active_slots is --max-batch-size when explicitly set, otherwise --n-parallel; --no-batch uses one slot. /health.context_size, /slots[].context_size, and --estimate-memory use this effective per-slot value. Startup rejects explicit budgets that would leave a slot below 512 tokens.

Example: configure a server for high-concurrency use:

mlxcel serve \
    --model ./models/llama-3.1-8b-4bit \
    --port 8080 \
    --n-parallel 8 \
    --max-batch-size 8 \
    --max-queue-depth 64 \
    --prefill-chunk-size 512

The explicit --prefill-chunk-size 512 in this example pins the chunk at 512 for both idle and contended ticks; omit it to keep the adaptive 2048/512 default. See Continuous Batching for how chunking and the KV admission watermark interact with the scheduler.

Speculative Decoding

Speculative decoding accelerates generation by using a drafter to propose tokens that the target model verifies. Server mode supports the DFlash and MTP drafter kinds, an ordinary smaller checkpoint as a full-model drafter, and drafter-free prompt lookup (--draft-kind prompt-lookup).

Flag Default Description
--draft-model PATH None Drafter checkpoint. Both server binaries accept --draft-model PATH and --model-draft PATH; their help output presents a different primary spelling.
--draft-max N 16 Accepted for llama-server compatibility (aliases --draft, --spec-draft-n-max, --draft-n). The value is reported as n_max in /props; it does not set the proposal width, which comes from --draft-block-size.
--draft-kind dflash\|mtp\|full-model\|prompt-lookup auto Force a drafter kind. full-model runs an ordinary smaller checkpoint that shares the target's tokenizer, and a readable model directory that is neither MTP nor DFlash is detected as full-model. prompt-lookup takes no drafter checkpoint (a --draft-model with it fails startup). Omitted values are auto-detected from the drafter config. See Prompt Lookup in mlxcel.
--draft-block-size N resolved at startup DFlash, MTP, or full-model block size. When unset, a width the drafter declares wins, then a measured per-device default, then 4 for MTP and full-model and 16 for DFlash; see Draft Block Width. With --draft-kind prompt-lookup it sets the largest proposal per round (default 7).
--prompt-lookup-max-batch N 2 Largest active decode batch at which a prompt-lookup row runs its own verify round. With more concurrent rows, every row takes the plain batched step. Must be at least 1.

DFlash example:

mlxcel serve \
    --model ./models/qwen3.5-27b-4bit \
    --draft-model ./models/Qwen3.5-27B-DFlash \
    --draft-kind dflash \
    --draft-block-size 16 \
    --port 8080

Chat Templates

mlxcel automatically reads the chat template from the model's tokenizer_config.json. You can override this with a custom template.

Flag Default Description
--chat-template TEMPLATE None Override with an inline Jinja2 template string.
--chat-template-file PATH None Override with a Jinja2 template file.

Template resolution order:

  1. --chat-template (inline string)
  2. --chat-template-file (file path)
  3. tokenizer_config.json chat_template field (automatic)
  4. Built-in fallback template

Optional Endpoints

Flag Default Description
--metrics Disabled Enable the /metrics endpoint (Prometheus-compatible text format).
--props Disabled Enable the /props endpoint (server properties).
--no-slots Enabled by default Disable the /slots endpoint.

Warmup

By default, the server generates one token on startup (and discards it) to pre-compile the Metal or CUDA compute pipeline. This eliminates latency on the first real request.

# Disable warmup (faster startup, but first request will be slower)
mlxcel serve --model ./models/my-model --no-warmup