Full Feature Reference

NovaMLX — Feature Reference

Production-grade, pure-Swift LLM / VLM / Audio / Image inference server for Apple Silicon. OpenAI-, Anthropic-, and Responses-API-compatible. Native macOS menu bar app. Built on MLX. Multi-node distributed inference, cloud proxy, load balancing, and a full key-management system.


Table of Contents


Inference Engine

NovaMLX runs LLM, VLM, audio, and image inference directly on Apple Silicon GPU via MLX, with zero external dependencies on Python or remote services.

Feature Details
Backends MLX (Apple Silicon GPU), lazy evaluation, unified memory
Model formats SafeTensors — 4-bit, 8-bit, FP16, NVFP4 pre-quantized
Sampling temperature, top_p, top_k, min_p, frequency_penalty, presence_penalty, repetition_penalty, seed
Stop control Stop strings, stop token IDs, max-token cap
Streaming SSE for OpenAI/Anthropic/Responses; raw bytes for audio/image
Staged evaluation Batched eval prevents Metal OOM for models >500 arrays (e.g., Ling-2.6-flash 61 GB)
CompiledSampler Precompiled sampling graph for hot-path token selection
MLXEngine.perform Thread-isolated model()+eval()+sample() wrapper for safe concurrency

Worker Subprocess Isolation

Each inference model runs in a dedicated worker subprocess supervised by WorkerSupervisor (Sources/NovaMLXInference/WorkerSupervisor.swift).

Feature Details
Process isolation Crash in one model cannot take down the server
Auto-restart Crash recovery with 2-second cooldown, request re-routing
Memory stats Tracks current / soft / hard RSS limits per worker
GPU memory Live Metal allocator pressure reporting
Request tracking In-flight request bookkeeping with auto-cleanup on crash
Progress callbacks Phased model-loading progress (init / weights / kv-cache / ready)

Multi-Modal Support

Modality Architectures Notes
Vision (VLM) Llava, LlavaNext, LlavaQwen2, Qwen2VL, Qwen2.5VL, Qwen3VL, Mllama, Gemma3, Gemma4, InternVLChat, Idefics3, PaliGemma, Phi3V, Pixtral, Molmo, Florence2, Mistral3 3D-mRoPE state requires ContinuousBatcher (not fused-decode)
Audio ASR Whisper, Qwen3-ASR 48 kHz recording via Core Audio
Audio TTS Qwen3-TTS (legacy), Dots TTS (current) Dots voice cloning supported
Image generation FLUX.1 (4-bit, 8-bit, FP16) Vendored flux.swift
Embeddings BERT, XLM-Roberta, ModernBert, Qwen3-ForTextEmbedding, Siglip, NomicBert Pooling: mean / cls / last-token
Reranking Cross-encoder rerankers Scored re-order of candidate passages

Model Architectures

ModelFamily registry (Sources/NovaMLXCore/Types.swift): llama, mistral, phi, qwen, gemma, starcoder, claude, bailing, gptOss, whisper, qwen3Asr, qwen3Tts, dotsTts, stableDiffusion, flux, other.

LLM families include: Llama 3 / 3.1 / 3.2 / 3.3, Mistral / Mixtral, Qwen 2 / 2.5 / 3 / 3.5 / 3.6, Gemma 2 / 3 / 4, Phi 3.5 / 4, StarCoder2, GPT-OSS (Harmony), Bailing-Hybrid (Ling series — MLA + GLA + MoE).

Family-specific defaults (in ModelFamilyRegistry):

Family KV precision Prefill Context
Llama / Mistral 4-bit 512 8192
Phi 32-bit 256 4096
Qwen 4-bit 512 8192
Gemma 32-bit 256 8192

Chat-template processorChatTemplateProcessorRegistry routes by (ModelFamily, ChatTemplateFormat) tuple. Family-specific processors handle control tokens, implicit thinking detection, and stop-sequence injection.

API Compatibility

Three wire formats share a single inference engine and tool-calling layer.

OpenAI-Compatible (Port 6590)

Endpoint Method Notes
/v1/models GET List loaded + downloaded models
/v1/models/{id} GET Model metadata
/v1/chat/completions POST Streaming + non-streaming
/v1/completions POST Legacy text completion
/v1/embeddings POST Text → vector
/v1/audio/transcriptions POST Whisper / Qwen3-ASR
/v1/audio/speech POST Dots / Qwen3-TTS
/v1/images/generations POST FLUX.1
/v1/images/edits POST FLUX.1 with mask
/v1/images/variations POST FLUX.1 variations
/v1/rerank POST Cross-encoder reranking

Anthropic-Compatible

Endpoint Method Notes
/v1/messages POST Streaming + non-streaming; messages, system, tools, tool_choice, thinking_budget
/v1/messages/count_tokens POST Pre-flight token count

Auth: x-api-key or Authorization: Bearer. anthropic-version: 2023-06-01 header required.

Responses API

Codex-compatible /v1/responses implementation.

Feature Details
Endpoint POST /v1/responses (stream + non-stream), GET/DELETE /v1/responses/{id}, POST /v1/responses/{id}/cancel
P0 tool_choice passthrough (auto / required / none / specific tool)
P1 17-field response echo (status, output, usage, completed_at, etc.)
P2 SSE seq field for client-side gap detection
ConversationStore previous_response_id resolves stored conversation history
Reasoning aliases reasoning.effortthinking_budget
Compact POST /v1/responses/compact truncates stored conversation
Input tokens POST /v1/responses/input_tokens exact tokenization count

Admin Endpoints (Port 6591)

Bearer-token auth via admin key. Full catalog:

  • Models — list / detail / download / cancel / load / unload / forget / benchmark / perplexity / cache stats
  • API Keys — CRUD, rotate, usage stats, per-key metrics
  • Tokenhub providers — CRUD, test, metrics
  • Load balancers — CRUD, member management, dry-run routing
  • Modelfiles — CRUD for custom model definitions
  • Stats / Info / Reset — server metrics, system info, reset
  • Log level — runtime log severity control

Structured Output

Mode Wire field Notes
JSON object response_format: {type: "json_object"} Forces valid JSON output
JSON schema response_format: {type: "json_schema", json_schema: {schema: ...}} Strict-schema constrained generation
Regex response_format: {type: "regex", regex: "..."} Regex-anchored output
GBNF grammar response_format: {type: "gbnf", gbnf: "..."} llama.cpp grammar format
Choice / Enum via schema enum One-of constrained selection

Tool Calling

Format Field Response shape
OpenAI tools: [{type:"function", function:{name, parameters}}] choices[0].message.tool_calls[]
Anthropic tools: [{name, description, input_schema}] content[].tool_use blocks
Responses via modelfile Extracted via regex + JSON parse

tool_choice: auto / required / none / specific tool / any (Anthropic). Bidirectional translation preserves tool id, name, and arguments across formats.

Control Token & Thinking Filtering

Subsystem Behavior
TurnStopProcessor Model-specific stop-token sets (<|turn|>, <|end|>, etc.); excludes channel tokens for channel-thinking models
ThinkingParser Implicit <think> tag handling; explicit thinking-budget pass-through
Semantic vs. protocol tokens Semantic tags (<think>) pass through; protocol tokens (<|turn|>) filtered
Per-model detection isImplicitThinkingModel flag per model ID
Finalize-before-stop Flushes parsed thinking before emitting stop chunk (Qwen3.6 streaming fix)
Channel-aware GPT-OSS Harmony <|channel|> tokens excluded from stop set

KV Cache & Prefix Share

Feature Details
SSD cache store Persistent cross-session KV cache at ~/.nova/cache/
Block hashing Content-addressable blocks via BlockHasher
Paged block pool Memory-efficient block management via PagedBlockPool
Auto-load on startup Rehydrates cache for warm models (hybrid models currently disabled due to Mamba+KV mix)
Hit/miss tracking Per-model cache statistics exposed via /admin/models/{id}/cache
Session reuse session_id request field pins a request to a KV-cache lineage; same session = same KV across requests. Works on /v1/chat/completions, /v1/messages, /v1/responses.

Clarification: Anthropic `cache_control` is intentionally not parsed

Anthropic's cache_control: { type: "ephemeral" } field exists for billing — it tells Anthropic's cloud which content blocks to charge cache-write pricing for. NovaMLX is a local inference server with no billing layer, so the field serves no purpose here: KV cache is reused automatically on every request that shares a prefix.

How we handle cache_control per routing path:

Path Behavior
Local inference (/v1/messages → MLX) Field silently dropped by Codable decode (no cache_control key on AnthropicContentBlock). KV cache reuse still happens automatically via prefix matching + session_id. No client action needed.
tknet: / lb: → native Anthropic upstream (raw passthrough) Field preserved verbatim in body. anthropic-version header always forwarded; anthropic-beta header forwarded when client sent it (so 1-hour cache TTL reaches the provider instead of silently degrading to 5 minutes).
tknet: / lb: → OpenAI-format upstream (Anthropic↔OpenAI bridge) Field dropped during translation (OpenAI chat/completions has no equivalent). Server emits a [WARN] [TokenhubBridge] log line so operators can see the silent downgrade.

TurboQuant KV Compression

4-bit affine-quantized KV cache with dynamic group sizing.

Feature Details
Compression 4-bit affine quantization for K and V tensors
Group sizing Dynamic per-layer group size based on head dim
Transparency Hidden from sampler — operates below sampling layer
Quality trade ~75% KV memory reduction with minimal quality loss on long context

Continuous Batching

Feature Details
Default batch 8 sequences (configurable)
Preemption Priority-based eviction under memory pressure
Specialized queues Separate paths for VLM, hybrid-attention, sessions, grammar-guided
Async streaming Priority-queued token emission per request
Metrics BatcherMetrics exposes queue depth, preemption rate, mean wait

Speculative Decoding

N-gram Spec Decoding

Free speculative decoding via n-gram token prediction (no draft model required). Lookahead window + acceptance sampling.

Draft-Model Spec Decoding

Feature Details
DraftModelRegistry Auto-injects recommended draft model per target model family
Built-in drafts Qwen3-0.6B-4bit, Llama-3.2-1B-4bit, Gemma-2-2B-4bit
API draft_model + num_draft_tokens request fields
EOS suppression Draft-only EOS tokens filtered to prevent premature stop
Limits Hybrid-attention (Mamba) targets unsupported; cross-vocab drafts unsupported
Status API SpecBoostStatus: .eligible / .active / .ineligible per model

Distributed Inference

Pipeline-parallel sharding across multiple Apple Silicon nodes over TCP / Thunderbolt.

Feature Details
Transport Raw TCP binary data plane; scale-adaptive control plane
Shard policy SlicedForwardPolicy — reflection-based layer slicing
ShardEngine Coordinates per-node forward pass
ClusterModelManager Cluster-wide activation / deactivation; ClusterModelState (idle / activating / ready / failed)
Remote sampling Argmax on worker; 4-byte token ID instead of full logits tensor
WorkerSupervisor Per-node worker lifecycle with heartbeat / health tracking
Auto-fallback Degrades to local inference on cluster failure
Backends compiled Ring (TCP) live; JACCL (RDMA) ready behind rdma_ctl flag
Profiling (measured) coord 31.8 ms, worker 33.7 ms, TCP 9 ms, tokenizer 0.3 ms; ~14 tok/s sequential ceiling; ~13.8 tok/s baseline with remote sampling
Real-world test Qwen3.6-27B across M4 Max + M4 Mac Mini via Thunderbolt → 1.8 tok/s pipeline-parallel

Audio (ASR / TTS / Voice Cloning)

Feature Details
Whisper ASR 48 kHz recording, language auto-detect, TranscriptionContainer for hot-swap
Qwen3-ASR Alternate ASR backend, same /v1/audio/transcriptions surface
Dots TTS Vendored mlx-swift-dots-tts; DotsTTSPipeline neural voice
Qwen3-TTS Legacy path; superseded by Dots
System voices macOS NSSpeechSynthesizer fallback
Voice cloning VoiceProfile manager at ~/.nova/voices/; multi-speaker; reference-audio cloning
VoiceCloneSheet UI Record / pick reference; preview; persist as named profile
Mic permission audio-input entitlement + NSMicrophoneUsageDescription injected via build.sh

Image Generation

Feature Details
Model FLUX.1 (4-bit, 8-bit, FP16)
Pipeline Vendored flux.swift FluxPipeline
Container ImageGenerationContainer for hot-load / unload
Endpoints /v1/images/generations, /v1/images/edits, /v1/images/variations
Output Base64 PNG; configurable height / width / steps / guidance
Service ImageGenerationService async API

Embeddings & Reranking

Feature Details
EmbeddingContainer Hot-loadable embedding models
Architectures BERT, XLM-Roberta, ModernBert, Qwen3-ForTextEmbedding, Siglip, NomicBert
Pooling mean / cls / last-token
Endpoint POST /v1/embeddings
RerankerContainer Cross-encoder rerankers
Endpoint POST /v1/rerank (candidates → scored candidates)

Session Management

Feature Details
Session ID session_id request field pins request to KV-cache lineage
Fork Branch a session into a new ID without copying KV
TTL Idle sessions evicted under memory pressure (LRU)
Cross-endpoint Same session works across OpenAI / Anthropic / Responses

MCP — Model Context Protocol

Feature Details
Transports stdio, SSE, streamable-HTTP
Tools MCPTool with JSON-schema input; namespaced server__tool naming
Resources Exposed via MCPServerConfig
Server status disconnected / connecting / connected / error
Tool exec MCPExecuteRequest / Response; timeout + headers configurable
Validation Input-schema enforcement before tool invocation

Agent Integration

Agent Built-in support
OpenClaw Tool-using agent
Hermes Agent Long-running reasoning agent
OpenCode Coding agent
Plugin system Extensible agent frameworks

AgentsPageView provides install / launch / configure / view-config UX.

Tokenhub Cloud Proxy

Proxy remote API providers through NovaMLX so all clients (Codex, Claude Code, Continue, etc.) can hit one local endpoint.

Feature Details
Provider catalog 20+ pre-configured: OpenAI, Anthropic, DeepSeek, GLM/Zhipu, Qwen/DashScope, Groq, Mistral, Moonshot, Yi, Together, Fireworks, OpenRouter, and more
Provider kinds Cloud-managed (tknet.ai session) vs. BYO-key
Routing tknet:<provider-id> model prefix → resolves provider
Passthrough Raw body forward; swaps model to provider.remoteModel
Vision backends Tier 1: local VLM; Tier 2: provider's anthropicEndpoint (e.g., GLM anthropic-proxy); Tier 3: visionCompanionModel; with image preprocessing + description injection
Provider metrics Success count, request count, avg latency, per-provider stats
Auth resolution Managed providers use session token; BYO-key uses provider.apiKey
Endpoint field anthropicEndpoint opt-in for providers that natively expose Anthropic format

Anthropic↔OpenAI Translation Bridge

When a client sends /v1/messages (Anthropic format) but the resolved provider speaks OpenAI only (DeepSeek, GLM, Qwen-compat, etc.), the bridge translates the request to OpenAI /chat/completions, forwards it, and rebuilds an AnthropicResponse.

Subsystem Behavior
Discriminator needsAnthropicBridge(provider, path): true when path is messages AND provider's anthropicEndpoint is unset
Inbound Decodes AnthropicRequest, maps via existing mapAnthropicMessages
Outbound body Builds OpenAI chat/completions: model, messages, tools, tool_choice, sampling, stop
Response Decodes OpenAIResponse, builds AnthropicResponse with text / thinking / tool_use blocks
Streaming Event-by-event state machine: OpenAI chunks → Anthropic message_start / content_block_start / content_block_delta(text_delta|thinking_delta|input_json_delta) / content_block_stop / message_delta(stop_reason, usage) / message_stop
Stop reason map stop → end_turn, tool_calls → tool_use, length → max_tokens, stop_sequence → stop_sequence
LB-transparent LB dispatcher routes lb: + messages through the same passthrough — bridge kicks in automatically
Files Sources/NovaMLXAPI/APIServer+TokenhubAnthropicBridge.swift

Load Balancers

Route requests across pools of local + remote models via lb:<slug> model prefix.

Feature Details
LBRouter strategies Tiered (default), round-robin, weighted, least-latency
Member kinds .local (inference service) and .remote (tokenhub provider)
LBProxy Per-request actor: picks member, tries candidates in order, retries on failure
Admin API 9 endpoints: CRUD for LBs + members, dry-run routing, stats
Per-member stats Success / fail / avg latency; surfaces in UI
UI LoadBalancersPageView: accordion rows, member picker, strategy config, per-LB play button
API formats Works across OpenAI / Anthropic / Responses (Anthropic via translation bridge; Responses via tknet: rewrite)

API Key Management

SQLite-backed API key system with hashing, rate limits, and whitelists.

Feature Details
Storage SQLite via APIKeyStore (replaces former api_keys.json)
Hashing SHA-256 (plaintext retained for reveal feature; opt-in DB access)
CRUD Create, read, update, delete via /admin/keys and UI
Rotate /admin/keys/{id}/rotate mints a new plaintext, invalidates old
Rate limits Per-key rateLimitPerSecond, maxTokensPerPeriod, maxRequestsPerPeriod with reset period (minute / hour / day)
Whitelists Per-key allowedModels[], allowedEndpoints[]
Usage tracking Total + period tokens / requests; per-model breakdown; last-used timestamp
Open-mode bypass When no keys configured, auth disabled (dev mode)
UI APIKeysPageView: whole-row accordion, eye-reveal toggle, copy-revealed button, usage stats with progress bars, whitelists
Admin vs user key Separate middleware: AdminAuthMiddleware (port 6591) vs APIKeyAuthMiddleware (port 6590)

Model Management

Feature Details
Model directory ~/.nova/models/<repo_id>/
Discovery modelManager.downloadedModels() + inferenceService.listLoadedModels()
Auto-load Request to unloaded model triggers load (configurable via ensureModelReady)
Auto-eviction LRU under memory pressure; never evicts mid-request
Restore on restart restoreModels() rehydrates last session's loaded set
loaded_models persistence SQLite table (was JSON, fixed wipe-on-restart bug)
Model settings Per-model overrides persisted in SQLite (model_settings table)
Model cards Fetch metadata from HuggingFace via /admin/api/hf/model-info
Forgetting /admin/models/{id}/forget — drops KV cache + container state

HuggingFace Integration

Feature Details
Download POST /admin/api/hf/download with repo_id + optional endpoint
Cancel POST /admin/api/hf/cancel by task ID; kills in-flight Task
Status polling GET /admin/api/hf/tasks returns per-file progress + speed + stall detection
Mirror support Configurable HF endpoint (default huggingface.co; CN users often set hf-mirror.com)
Idempotent resume cancelTasksForRepo kills any in-flight task before starting new (prevents click-spam races)
HEAD probe 3-second reachability check before each file download (fail-fast on blocked endpoints)
Phase UI Client shows: Connecting / Downloading (MB/s) / Stalled (Ns since last byte) / Endpoint unreachable
Partial-scan Detects *.download temp files on launch → surfaces as .failed tasks for manual Resume
Xet CDN Auto-follows cas-bridge.xethub.hf.co redirects

Modelfile System

Custom model definitions analogous to Ollama Modelfiles.

Feature Details
Storage SQLite modelfiles table
Fields name, base_model, system, template, parameters, adapter, tools
Admin API CRUD at /admin/modelfiles
Resolution Modelfile name resolves like a model ID
Tool defs Static tool definitions embedded in modelfile

Memory Management

Subsystem Behavior
ProcessMemoryEnforcer Hard RSS cap via ProcessInfo.memoryPressure + proactive trim
MemoryBudgetTracker GPU memory budget per active model
WiredMemoryTicket Reserves wired Metal memory before allocation
Auto mode Process monitors system pressure, evicts when needed
Disabled mode No cap (dev / benchmark)
Percent mode Cap = N% of system RAM
Fixed mode Explicit GB cap
Staged eval Large models load in batches to avoid Metal OOM

Per-Model Settings

Persisted per model ID, override defaults at request time:

  • Sampling defaults (temperature, maxTokens, topP, repeatPenalty)
  • KV precision (4-bit / 8-bit / 32-bit)
  • Context window override
  • TurboQuant toggle
  • Vision strategy
  • Companion vision model
  • Thinking defaults (enableThinking, thinkingBudget, preserveThinking)
  • Keep-alive interval

Observability & Benchmarking

Tool Endpoint Notes
Benchmark /admin/models/{id}/benchmark Measures TPS, TTFT, memory, peak
Perplexity /admin/models/{id}/perplexity Standard perplexity on test set
Cache stats /admin/models/{id}/cache KV cache hit / miss / size
Server stats /admin/stats Aggregate: total tokens, active reqs, uptime
System info /admin/info Chip, cores, RAM, GPU, macOS version
Logging ~/.nova/novamlx.log Rotating file log; runtime level via admin
Log levels debug / info / warning / error POST /admin/log/level
Metrics headers X-Tokenhub-Provider, X-Model-Cold-Load, X-Model-Load-Time-Ms Per-response introspection
InferenceStats Live TPS, peak TPS, tokens generated, active requests, worker CPU Polled every 2 s by UI

macOS Menu Bar App

Native SwiftUI menu bar app. Status icon + dropdown + popout window.

Pages

Page Highlights
Status Live TPS chart (90-sample window, peak tracking, zero-trim), CPU/mem/GPU grid, device info, peak TPS
Dashboard One-screen overview: loaded models, active requests, memory, uptime, quick-load
Local Inference Active models with unload + copy-name + play-in-Playground; downloaded models with type tabs (All / LLM / VLM / Embed / Audio / Image); model card
Downloads Category tabs, suggested-model cards, phase-aware progress, stall detection, mirror config
Playground (Chat) Unified LLM / ASR / TTS / Image; model-type auto-detect; section-header picker (LOCAL DIRECT IN-PROC vs TOKENHUB HTTP); parameter sliders; Disable-Thinking toggle; sticky auto-scroll; copy cURL (OpenAI/Anthropic/Responses); ASR mic + TTS speaker + voice clone
Tokenhub 20+ provider catalog; CRUD; per-provider API models with copy + play buttons; endpoint testing
Load Balancers Accordion rows; member picker (local + remote); strategy + stats; play button per row
API Keys Whole-row accordion; eye reveal; copy revealed; usage bars; rate-limit display; whitelists
Cluster Network scan (Thunderbolt + ARP); worker monitoring with health states; per-node model readiness
Settings HF endpoint + mirror; memory mode; log level; cluster toggle; TurboQuant; tknet.ai account link
Audio Dedicated ASR / TTS surface (separate from Playground)
Agents Install / launch / configure OpenClaw, Hermes, OpenCode

Cross-page UX

Feature Details
Pick-to-Playground play.circle button on Active Models / Tokenhub API models / Load Balancers → jumps to Playground + pre-selects model
Copy cURL buttons In Playground Parameters: OpenAI / Anthropic / Responses — emit ${NOVA_API_KEY} placeholder so secret never enters clipboard
Sticky auto-scroll 80 pt threshold via MessageListBottomOffsetKey PreferenceKey
Model picker inferModeFromName + autoDetectMode switch mode (LLM / ASR / TTS / Image) automatically
HF Endpoint settings Mirror swap without restart — propagated via NovaMLXConfiguration.shared

Internationalization

9 languages, auto-detected from system locale with English fallback.

English, Simplified Chinese (zh-Hans), Traditional Chinese HK (zh-Hant-HK), Traditional Chinese TW (zh-Hant-TW), Japanese, Korean, French, German, Russian.

Security & Middleware

Layer Behavior
CORS Configurable allowed origins; preflight handling
Rate limiter Token bucket per API key + per IP; global + per-route limiters
Error middleware NovaMLXErrorMiddleware normalizes errors to OpenAI/Anthropic shape; Retry-After header on 429
Admin auth AdminAuthMiddleware on port 6591 — admin key required
API auth APIKeyAuthMiddleware on port 6590 — Bearer or x-api-key; open-mode bypass when no keys
Strict headers X-Content-Type-Options, Strict-Transport-Security, X-Frame-Options, Referrer-Policy
Request ID x-request-id per request for tracing
Cloud session AuthCache for tknet.ai session token; cloud validation endpoint

Homebrew Distribution

Channel Details
Formula Formula/novamlx.rb
Build script ./build.sh — UUID sync, codesigning, MLX shader compile, bundle assembly
DMG Script-based disk image packaging
Codesigning codesign --force --deep --sign - required post-deploy (else macOS SIGKILLs worker)
Entitlements audio-input, com.apple.security.device.camera (where applicable), NSMicrophoneUsageDescription injected via PlistBuddy

TCC Watcher

Feature Details
Purpose Auto-dismiss macOS TCC privacy prompts that block automation
Bundle TCCWatcher.app (CFBundleIdentifier com.novamlx.TCCWatcher)
Install Scripts/install-tcc-watcher.sh — sets up LaunchAgent
Mechanism Watches for TCC prompts via System Events; inlined inspectWindow in main tell block (fixes context-prop bug)
One-time setup User adds TCCWatcher.app via + button in System Settings → Privacy → Accessibility (macOS 14+ no auto-prompt)

Configuration

`ServerConfig` (`~/.nova/config.json` or SQLite)

Field Default Notes
server.port 6590 Public API port
server.adminPort 6591 Admin API port
server.cluster null Enables distributed mode
server.apiKey null Open-mode if null
server.corsOrigins * CORS allow-list
huggingface.endpoint huggingface.co Mirror swap
autoLoad enabled Pre-load models on startup
memory.mode auto auto / disabled / percent / fixed
memory.limitGB null Fixed cap
scaleTokenCount enabled Scale reported tokens for context accounting
logLevel info debug / info / warning / error

`NOVA_DIR`

Precedence Source
1 (highest) ~/.config/novamlx/path file contents
2 NOVA_DIR environment variable
3 (default) ~/.nova

Multi-instance supported. Only models/ is shareable across instances.

Engine Configuration

Per-family defaults in ModelFamilyRegistry — KV precision, prefill chunk, context window, draft-model recommendation.

Architecture Overview

┌─────────────────────────────────────────────────────────────┐
│  Clients: Codex / Claude Code / Continue / OpenAI SDK /     │
│           Anthropic SDK / curl                              │
└────────────────────────┬────────────────────────────────────┘
                         │
            ┌────────────▼────────────┐
            │   Hummingbird HTTP/2    │  Port 6590 (api) + 6591 (admin)
            │   + CORS + RateLimit    │
            │   + Auth Middleware     │
            └────────────┬────────────┘
                         │
   ┌─────────────────────┼──────────────────────────┐
   │                     │                          │
┌──▼─────────┐  ┌────────▼─────────┐  ┌────────────▼───────────┐
│  Local     │  │  Tokenhub Proxy  │  │  LBProxy (lb:<slug>)   │
│  Inference │  │  + Anthropic     │  │  → routes to local or  │
│  (Worker)  │  │    Bridge        │  │    tokenhub member     │
└──┬─────────┘  └────────┬─────────┘  └────────────────────────┘
   │                     │
┌──▼─────────────────────▼──┐
│  MLX Engine               │
│  - ContinuousBatcher      │
│  - TurboQuant KV Cache    │
│  - Speculative Decoding   │
│  - Tool calling           │
│  - Structured output      │
│  - Chat template proc     │
└──┬────────────────────────┘
   │
┌──▼──────────────────────┐  ┌──────────────────────────┐
│  WorkerSupervisor       │  │  Distributed (optional)  │
│  (subprocess isolation) │  │  Ring TCP / Thunderbolt  │
└─────────────────────────┘  └──────────────────────────┘

Data persistence: NovaDB (SQLite + GRDB) — 14 tables covering api_keys, providers, load_balancers, modelfiles, loaded_models, model_settings, metrics, cluster_policy, conversations (Responses), and more. Auto-migrates legacy JSON on first launch.

Quick Start

# Install (Homebrew)
brew install --head novamlx

# Or build from source
git clone https://github.com/novamlx/novamlx && cd novamlx
./build.sh
open dist/NovaMLX.app

# Set your API key (or run in open mode without one)
export NOVA_API_KEY=$(openssl rand -hex 24)

# List models
curl http://localhost:6590/v1/models \
  -H "Authorization: Bearer $NOVA_API_KEY"

# Chat
curl http://localhost:6590/v1/chat/completions \
  -H "Authorization: Bearer $NOVA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mlx-community/Qwen3.6-27B-4bit",
    "messages": [{"role":"user","content":"Hello"}]
  }'

# Anthropic format
curl http://localhost:6590/v1/messages \
  -H "x-api-key: $NOVA_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mlx-community/Qwen3.6-27B-4bit",
    "max_tokens": 1024,
    "messages": [{"role":"user","content":"Hello"}]
  }'

# Proxy a cloud model (set up via Tokenhub UI first)
curl http://localhost:6590/v1/chat/completions \
  -H "Authorization: Bearer $NOVA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "tknet:deepseek-v4-flash",
    "messages": [{"role":"user","content":"Hello"}]
  }'

# Load balancer (create via UI first, then use lb:<slug>)
curl http://localhost:6590/v1/chat/completions \
  -H "Authorization: Bearer $NOVA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "lb:my-pool",
    "messages": [{"role":"user","content":"Hello"}]
  }'

NovaMLXBuilt by hlky and contributors. Released under the MIT License.