Rust-native GGUF + MLX inference engine. Pull from Ollama/HuggingFace, serve over gRPC and OpenAI-compatible HTTP. Multi-model, memory-aware, Metal/CUDA/Vulkan
Rust
2
303 commits
updated Sep 12, 2026
Spindle + LL(ama). A Rust-native GGUF and MLX inference engine with model management.
A single binary that pulls models from Ollama's registry or HuggingFace, manages local storage, and serves streaming inference over gRPC and HTTP. Multi-model, memory-aware, GPU-accelerated, with an OpenAI-compatible API. On Apple Silicon, runs MLX models natively via a Swift bridge in addition to GGUF via llama.cpp.
# Build with HTTP support
cargo build --release --features cli,http
# Pull a model
spindll pull llama3.1:8b
# Or import from an existing Ollama installation
spindll import --from-ollama
# Start the server (gRPC on 50051, HTTP on 8080)
spindll serve
Models are loaded automatically on first request, or explicitly via the Load RPC / POST /load endpoint.
InferenceBackend trait dispatches to llama.cpp for GGUF and mlx-swift-lm for MLX, with an extension point for new enginespull without --quant picks q4_k_m by priority list (q4_k_m > q5_k_m > q4_0 > … > fp16) instead of grabbing the first GGUF in the repo/v1/chat/completions, /v1/completions, and tool/function calling for AnythingLLM, Open WebUI, and any OpenAI client/v1/messages) and OpenAI Responses (/v1/responses), so Claude Code and Codex CLI run against spindll as a local backend<model>.jinja sidecar override (raw Jinja or a built-in name like gemma) for models shipping a broken or missing templatespindll search <query> [--limit N] # search HuggingFace + Ollama, ranked by hardware
spindll pull <model> [flags] # pull from Ollama registry or HuggingFace
spindll list # show local models with metadata (alias: ls)
spindll rm <model> [flags] # delete a local model, alias: remove (prompts for external sources)
spindll run <model> "prompt" [flags] # one-shot inference (no server)
spindll bench <model> [other] # benchmark one or two models (debug builds only)
spindll serve [model] [options] # start gRPC + HTTP server, optionally preloading a model
spindll load <model> [--port N] # load a model into a running server
spindll unload <model> [--port N] # drop a model from memory (stays on disk)
spindll import [OPTIONS] # import models (from Ollama, HuggingFace cache, or file path)
spindll status # query a running server
Model names follow Ollama conventions (llama3.1:8b, qwen2:0.5b) or HuggingFace repos (TheBloke/Llama-3-8B-GGUF, mlx-community/Meta-Llama-3.1-8B-Instruct-4bit).
--quant <STR> Pick a specific quant (e.g. q4_k_m, q5_k_m, fp16). Without
this flag, the picker prefers q4_k_m by default.
--gguf Force GGUF, skip MLX resolution on Apple Silicon
--mlx Force MLX, error if no MLX equivalent is found
--from-ollama Auto-discover and import models from local Ollama cache
--from-hf Auto-discover and import models from local HuggingFace cache
<PATH> Import a specific GGUF or MLX model from arbitrary path
(validates the file before importing via symlink)
--purge Skip confirmation prompts when removing externally-imported
models (models from Ollama cache, HF cache, or manual paths).
Spindll-downloaded models always delete without prompting.
--ctx-size <N> Context window size [default: 2048]
--budget <SIZE> Memory budget (e.g. "8G", omit=live RAM, "0"=total RAM)
--kv-cache [<SIZE>] Enable KV cache for prompt prefixes [default: 2G when enabled]
--port <PORT> gRPC port [default: 50051]
--http-port <PORT> HTTP/SSE port [default: 8080]
--ctx-size <N> Context window size [default: 2048]
--gpu-layers <N> GPU layers (omit to auto-detect)
--budget <SIZE> Memory budget, e.g. "8G". Default: full live availability
(free + inactive + purgeable + speculative on macOS;
sysinfo's available_memory elsewhere). Pass "0" to use
total RAM (trust unified-memory paging).
--kv-cache [<SIZE>] Enable KV cache for prompt prefixes [default: 2G]
--batch-slots <N> Concurrent sequence slots per model [default: 0 = disabled]
--ram-cache [<SIZE>] Keep recently-evicted models warm in RAM [default: 4G; no-op on macOS]
While serve is running it writes a JSON lockfile (pid, grpc_port, http_port) to the system temp dir. spindll status reads this file to auto-detect the port, so --port is optional when a local server is running. Stale lockfiles are cleaned automatically when the referenced PID is no longer alive.
Full API reference covering HTTP, OpenAI-compatible /v1, gRPC, and Rust library usage: docs/README.md
Quick summary of available interfaces:
| Interface | Port | Feature flag | Use case |
|---|---|---|---|
| gRPC | 50051 | none (always on) | Programmatic access, mesh integrations |
| HTTP/SSE | 8080 | http | Web frontends, custom integrations |
OpenAI /v1 | 8080 | http | AnythingLLM, Open WebUI, any OpenAI client (chat, completions, tool calling) |
| Agent APIs | 8080 | http | Claude Code (/v1/messages), Codex CLI (/v1/responses) |
[dependencies]
spindll = { git = "https://github.com/Iito/spindll.git" }
use spindll::engine::{ModelManager, GenerateParams};
use spindll::model_store::ModelStore;
let store = ModelStore::new(None);
let path = store.resolve_model_path("llama3.1:8b")?;
let digest = store.resolve_model_digest("llama3.1:8b").unwrap_or_default();
let manager = ModelManager::new(2048, None, 0)?;
manager.load_model_with_digest("llama3.1:8b", &path, None, digest)?;
manager.generate("llama3.1:8b", "Hello!", &GenerateParams::default(), None, |token| {
print!("{token}");
true
})?;
See docs/api-rust.md for the full library API including batch scheduling, KV cache, and server startup.
CLI / gRPC / HTTP+SSE / OpenAI /v1
|
Model Manager (multi-model slots, LRU eviction, memory budget)
| |
Batch Scheduler Per-request context
(continuous batching, (KV cache, encryption)
sequence pooling)
| |
Inference Backends (`InferenceBackend` trait)
│ │
llama.cpp via llama-cpp-2 mlx-swift-lm via Swift FFI
(GGUF, all platforms, (MLX, Apple Silicon only,
GPU offload) --features mlx)
|
Model Store (Ollama registry, HuggingFace, GGUF metadata, local registry)
Models are stored in ~/.spindll/models/<repo>/<file>. A JSON registry at ~/.spindll/registry.json tracks downloaded models with GGUF metadata. KV cache files are stored in ~/.spindll/cache/.
| Flag | Description |
|---|---|
cli | Standalone binary (clap argument parsing, pretty logging) |
http | HTTP/SSE server with OpenAI-compatible /v1 API (axum) |
mlx | MLX Swift backend on aarch64-apple-darwin (links against the bundled mlx_bridge Swift package) |
cuda | CUDA GPU support in llama.cpp |
metal | Metal GPU support in llama.cpp |
vulkan | Vulkan GPU support in llama.cpp |
The gRPC server and core engine are always compiled -- no feature flag needed for library consumers or for embedding spindll in another binary.
--features mlx on Apple Silicon)On a fresh Ubuntu install, install these additional system packages:
sudo apt install -y \
build-essential pkg-config cmake \
protobuf-compiler \
libssl-dev \
clang libclang-dev
GitHub Actions runners come with these pre-installed, so CI succeeds without explicit setup. Bare Ubuntu requires the full list.
The release binary links dynamically against system libraries. On Linux (glibc), users need:
sudo apt install -y libssl3 libgomp1
(These are pre-installed on Ubuntu/Debian/Fedora desktop; minimal server images require the install.)
macOS release binaries are self-contained; no runtime dependencies.
Licensed under the Apache License, Version 2.0 — see LICENSE.
Copyright 2026 Iito and sarmientoF.
Rust
87.5%
Swift
7.6%
Shell
4.5%
Rust-native GGUF + MLX inference engine. Pull from Ollama/HuggingFace, serve over gRPC and OpenAI-compatible HTTP. Multi-model, memory-aware, Metal/CUDA/Vulkan
Rust
2
303 commits
updated Sep 12, 2026
Spindle + LL(ama). A Rust-native GGUF and MLX inference engine with model management.
A single binary that pulls models from Ollama's registry or HuggingFace, manages local storage, and serves streaming inference over gRPC and HTTP. Multi-model, memory-aware, GPU-accelerated, with an OpenAI-compatible API. On Apple Silicon, runs MLX models natively via a Swift bridge in addition to GGUF via llama.cpp.
# Build with HTTP support
cargo build --release --features cli,http
# Pull a model
spindll pull llama3.1:8b
# Or import from an existing Ollama installation
spindll import --from-ollama
# Start the server (gRPC on 50051, HTTP on 8080)
spindll serve
Models are loaded automatically on first request, or explicitly via the Load RPC / POST /load endpoint.
InferenceBackend trait dispatches to llama.cpp for GGUF and mlx-swift-lm for MLX, with an extension point for new enginespull without --quant picks q4_k_m by priority list (q4_k_m > q5_k_m > q4_0 > … > fp16) instead of grabbing the first GGUF in the repo/v1/chat/completions, /v1/completions, and tool/function calling for AnythingLLM, Open WebUI, and any OpenAI client/v1/messages) and OpenAI Responses (/v1/responses), so Claude Code and Codex CLI run against spindll as a local backend<model>.jinja sidecar override (raw Jinja or a built-in name like gemma) for models shipping a broken or missing templatespindll search <query> [--limit N] # search HuggingFace + Ollama, ranked by hardware
spindll pull <model> [flags] # pull from Ollama registry or HuggingFace
spindll list # show local models with metadata (alias: ls)
spindll rm <model> [flags] # delete a local model, alias: remove (prompts for external sources)
spindll run <model> "prompt" [flags] # one-shot inference (no server)
spindll bench <model> [other] # benchmark one or two models (debug builds only)
spindll serve [model] [options] # start gRPC + HTTP server, optionally preloading a model
spindll load <model> [--port N] # load a model into a running server
spindll unload <model> [--port N] # drop a model from memory (stays on disk)
spindll import [OPTIONS] # import models (from Ollama, HuggingFace cache, or file path)
spindll status # query a running server
Model names follow Ollama conventions (llama3.1:8b, qwen2:0.5b) or HuggingFace repos (TheBloke/Llama-3-8B-GGUF, mlx-community/Meta-Llama-3.1-8B-Instruct-4bit).
--quant <STR> Pick a specific quant (e.g. q4_k_m, q5_k_m, fp16). Without
this flag, the picker prefers q4_k_m by default.
--gguf Force GGUF, skip MLX resolution on Apple Silicon
--mlx Force MLX, error if no MLX equivalent is found
--from-ollama Auto-discover and import models from local Ollama cache
--from-hf Auto-discover and import models from local HuggingFace cache
<PATH> Import a specific GGUF or MLX model from arbitrary path
(validates the file before importing via symlink)
--purge Skip confirmation prompts when removing externally-imported
models (models from Ollama cache, HF cache, or manual paths).
Spindll-downloaded models always delete without prompting.
--ctx-size <N> Context window size [default: 2048]
--budget <SIZE> Memory budget (e.g. "8G", omit=live RAM, "0"=total RAM)
--kv-cache [<SIZE>] Enable KV cache for prompt prefixes [default: 2G when enabled]
--port <PORT> gRPC port [default: 50051]
--http-port <PORT> HTTP/SSE port [default: 8080]
--ctx-size <N> Context window size [default: 2048]
--gpu-layers <N> GPU layers (omit to auto-detect)
--budget <SIZE> Memory budget, e.g. "8G". Default: full live availability
(free + inactive + purgeable + speculative on macOS;
sysinfo's available_memory elsewhere). Pass "0" to use
total RAM (trust unified-memory paging).
--kv-cache [<SIZE>] Enable KV cache for prompt prefixes [default: 2G]
--batch-slots <N> Concurrent sequence slots per model [default: 0 = disabled]
--ram-cache [<SIZE>] Keep recently-evicted models warm in RAM [default: 4G; no-op on macOS]
While serve is running it writes a JSON lockfile (pid, grpc_port, http_port) to the system temp dir. spindll status reads this file to auto-detect the port, so --port is optional when a local server is running. Stale lockfiles are cleaned automatically when the referenced PID is no longer alive.
Full API reference covering HTTP, OpenAI-compatible /v1, gRPC, and Rust library usage: docs/README.md
Quick summary of available interfaces:
| Interface | Port | Feature flag | Use case |
|---|---|---|---|
| gRPC | 50051 | none (always on) | Programmatic access, mesh integrations |
| HTTP/SSE | 8080 | http | Web frontends, custom integrations |
OpenAI /v1 | 8080 | http | AnythingLLM, Open WebUI, any OpenAI client (chat, completions, tool calling) |
| Agent APIs | 8080 | http | Claude Code (/v1/messages), Codex CLI (/v1/responses) |
[dependencies]
spindll = { git = "https://github.com/Iito/spindll.git" }
use spindll::engine::{ModelManager, GenerateParams};
use spindll::model_store::ModelStore;
let store = ModelStore::new(None);
let path = store.resolve_model_path("llama3.1:8b")?;
let digest = store.resolve_model_digest("llama3.1:8b").unwrap_or_default();
let manager = ModelManager::new(2048, None, 0)?;
manager.load_model_with_digest("llama3.1:8b", &path, None, digest)?;
manager.generate("llama3.1:8b", "Hello!", &GenerateParams::default(), None, |token| {
print!("{token}");
true
})?;
See docs/api-rust.md for the full library API including batch scheduling, KV cache, and server startup.
CLI / gRPC / HTTP+SSE / OpenAI /v1
|
Model Manager (multi-model slots, LRU eviction, memory budget)
| |
Batch Scheduler Per-request context
(continuous batching, (KV cache, encryption)
sequence pooling)
| |
Inference Backends (`InferenceBackend` trait)
│ │
llama.cpp via llama-cpp-2 mlx-swift-lm via Swift FFI
(GGUF, all platforms, (MLX, Apple Silicon only,
GPU offload) --features mlx)
|
Model Store (Ollama registry, HuggingFace, GGUF metadata, local registry)
Models are stored in ~/.spindll/models/<repo>/<file>. A JSON registry at ~/.spindll/registry.json tracks downloaded models with GGUF metadata. KV cache files are stored in ~/.spindll/cache/.
| Flag | Description |
|---|---|
cli | Standalone binary (clap argument parsing, pretty logging) |
http | HTTP/SSE server with OpenAI-compatible /v1 API (axum) |
mlx | MLX Swift backend on aarch64-apple-darwin (links against the bundled mlx_bridge Swift package) |
cuda | CUDA GPU support in llama.cpp |
metal | Metal GPU support in llama.cpp |
vulkan | Vulkan GPU support in llama.cpp |
The gRPC server and core engine are always compiled -- no feature flag needed for library consumers or for embedding spindll in another binary.
--features mlx on Apple Silicon)On a fresh Ubuntu install, install these additional system packages:
sudo apt install -y \
build-essential pkg-config cmake \
protobuf-compiler \
libssl-dev \
clang libclang-dev
GitHub Actions runners come with these pre-installed, so CI succeeds without explicit setup. Bare Ubuntu requires the full list.
The release binary links dynamically against system libraries. On Linux (glibc), users need:
sudo apt install -y libssl3 libgomp1
(These are pre-installed on Ubuntu/Debian/Fedora desktop; minimal server images require the install.)
macOS release binaries are self-contained; no runtime dependencies.
Licensed under the Apache License, Version 2.0 — see LICENSE.
Copyright 2026 Iito and sarmientoF.
Rust
87.5%
Swift
7.6%
Shell
4.5%