LLamaSharp is the most widely used .NET wrapper around llama.cpp. llmdot is a different approach to the same problem — a managed-by-default .NET runtime that reads GGUF directly, without a native engine underneath. Both are valid. They make almost opposite choices about how to get there, and the right pick depends on what you value in the deployment and packaging story.
This is the most direct comparison we draw, so we want to be fair about it.
The shared ground
Both projects target .NET developers who want to run local GGUF language models. Both let you load a quantized model from disk and stream tokens through idiomatic async APIs. Both can hook into Microsoft.Extensions.AI patterns. Both run on CPU and have a path to GPU acceleration. Either one can plausibly power a chat feature, a local agent, an offline summarizer, or a desktop AI capability inside a .NET application.
If you only care that “a small model runs in my .NET app,” either one is a credible answer.
Where they differ
The differences are in how each project actually executes the model.
LLamaSharp is a .NET binding over the upstream llama.cpp engine. It ships native binaries for the supported platforms, brings in upstream’s broad model coverage, and inherits upstream’s mature performance characteristics on the supported hardware paths.
llmdot is a pure-managed .NET runtime. It parses GGUF directly in C#, resolves a TransformerConfig from metadata, executes the model through four architecture-agnostic templates, and exposes optional Metal and Vulkan backends through an IComputeBackend contract on top of the managed CPU path. There is no native engine underneath. There is no llama.cpp dependency.
| Dimension | LLamaSharp | llmdot |
|---|---|---|
| Engine | Native llama.cpp via bindings | Pure managed .NET runtime |
| Distribution | NuGet + native binaries per RID | NuGet (managed); optional native backend packages |
| Model format | GGUF (via upstream) | GGUF (parsed directly) |
| Model coverage | Whatever upstream supports | 1–8B decoders via 4 templates (LLaMA-like, GPT-NeoX-like, Gemma-like, LFM2-like) |
| NativeAOT / trimming | Constrained by native dep | Designed for it |
| Single-file publish | Native assets must travel | Managed core only |
| GPU acceleration | Upstream backends (CUDA, Metal, Vulkan, etc.) | Optional per-op via IComputeBackend (Metal in dispatch, Vulkan structurally complete) |
| Maturity | Production-grade | Pre-alpha, active development |
| Strength | Performance and breadth | Packaging and deployment ergonomics |
When LLamaSharp is the better pick
If your priorities are peak throughput on a known target, the broadest possible model support today, and the longest production track record, LLamaSharp is the more conservative choice. Native llama.cpp is a mature engine with years of upstream tuning. The GPU paths are well-trodden. If you are deploying onto hardware you control, where you can reasonably guarantee the right native binaries are present, the throughput advantage is real.
It is also the right choice if you need to run a model family that llmdot does not yet target — anything outside the 1–8B decoder catalog, encoder-decoder workloads, or families that are not yet covered by one of llmdot’s four templates.
When llmdot is the better pick
If your priorities are managed deployment, NativeAOT compatibility, single-file publish, and a trimming-friendly install, llmdot is built for that case. The core package has no native runtime dependencies. The same DLL runs on Windows, Linux, and macOS without per-RID native assets. The runtime cooperates with dotnet publish instead of fighting it.
It is also the better pick if you value architectural transparency — the execution path is C# you can read, the kernels are Span<T> and Vector<T>, the dequantization is in-tree, and the model graph is parameterized by a TransformerConfig you can inspect. Debugging, profiling, and reasoning about behavior happen in the same toolchain you already use for the rest of your application.
What we are honest about
llmdot is pre-alpha. The spec and architecture are stable, but the implementation is in active development. LLamaSharp is production-used today; we are not. If you need to ship a feature this quarter and you do not have the appetite for an evolving runtime, do not pick us.
We are also honest that we will not beat a tuned native engine on every hardware target. That is a non-goal. We expect to be competitive enough on the model sizes and quantizations we target — 1–8B in Q4_K_M, Q5_K_M, Q8_0 and similar — that the packaging and deployment benefits dominate for the use cases we are designed for.
How to choose
If you are running a small quantized model from a .NET application and what you have been fighting is the native binary story, evaluate llmdot. If you are running heavy workloads on a controlled GPU box and what you care about is throughput, stay with LLamaSharp. Many shops will end up with both: LLamaSharp for the hot serving path, llmdot for the desktop, edge, and worker scenarios where managed deployment matters more than peak tokens per second.
We respect the work that has gone into LLamaSharp. We are not trying to replace it. We are trying to occupy a different position in the same problem space — one that the existing options were not directly serving.