Find the best local LLM that actually runs on your hardware.
Auto-detects your GPU/CPU/RAM and ranks the top models from HuggingFace that fit your system.
Run the recommendation command once, with no project setup.
uvx whichllm@latest
Simulate a GPU before you buy hardware.
uvx whichllm@latest --gpu "RTX 4090"
Install it when you use it often.
uv tool install whichllm
uv tool upgrade whichllm # update an existing install
Other install paths.
brew install andyyyy64/whichllm/whichllm
pip install whichllm
By default, whichllm is ambitious. It ranks the best model that looks runnable on your machine, including partial RAM offload and near-edge VRAM fits when they seem usable.
If you want a more comfortable LM Studio-style recommendation, start with:
uvx whichllm@latest --gpu-only --speed usable --vram-headroom 1GB
This keeps only models that fit fully in GPU VRAM, filters out slow estimates, and leaves extra VRAM for runtime overhead.
If LM Studio still says the model is slightly too large, increase the headroom:
uvx whichllm@latest --gpu-only --speed usable --vram-headroom 1.5GB
After install, run whichllm directly. For one-off runs, replace whichllm
with uvx whichllm@latest.
# Best models for this machine
whichllm
# Pretend you have a specific GPU
whichllm --gpu "RTX 4090"
# Override detected iGPU/unified-memory limits
whichllm --vram 8 --ram-bandwidth 68
# Only show models that fit fully in GPU VRAM
whichllm --gpu-only
whichllm --fit gpu
# Simulate a multi-GPU workstation
whichllm --gpu "2x RTX 4090"
# Hide models that are technically runnable but too slow
whichllm --speed usable
whichllm --speed fast
# Pasteable GitHub / Slack / Discord output
whichllm --markdown
# Compare upgrade candidates
whichllm upgrade "RTX 4090" "RTX 5090" "H100"
# Find the GPU needed for a model
whichllm plan "llama 3 70b"
# Start a chat with a model
whichllm run "qwen 2.5 1.5b gguf"
# Print copy-paste Python
whichllm snippet "qwen 7b"
# Return JSON for scripts
whichllm --top 1 --json

$ whichllm --gpu "RTX 4090"
#1 Qwen/Qwen3.6-27B 27.8B Q5_K_M score 92.8 27 t/s
#2 Qwen/Qwen3-32B 32.0B Q4_K_M score 83.0 31 t/s
#3 Qwen/Qwen3-30B-A3B 30.0B Q5_K_M score 82.7 102 t/s
The 32B model fits your card fine — whichllm still ranks the 27B #1, because it scores higher on real benchmarks and is a newer generation. A size-only "what fits?" tool would hand you the bigger one. That gap is the whole point of whichllm. (Note #3: a MoE model at 102 t/s — speed is ranked on active params, quality on total.)
Real top picks (snapshot 2026-05 — your results track live HuggingFace data, this is not a static list):
| Hardware | VRAM | Top pick | Speed |
|---|---|---|---|
| RTX 5090 | 32 GB | Qwen3.6-27B · Q6_K · score 94.7 |
~40 t/s |
| RTX 4090 / 3090 | 24 GB | Qwen3.6-27B · Q5_K_M · score 92.8 |
~27 t/s |
| RTX 4060 | 8 GB | Qwen3-14B · Q3_K_M · score 71.0 |
~22 t/s |
| Apple M3 Max | 36 GB | Qwen3.6-27B · Q5_K_M · score 89.4 |
~9 t/s |
| CPU only | — | gpt-oss-20b (MoE) · Q4_K_M · score 45.2 |
~6 t/s |
whichllm --gpu "<your card>" simulates any of these before you buy.
By default, rankings include full-GPU, partial-offload, and CPU-only
candidates when they are usable. Use --gpu-only or --fit full-gpu when
you only want models that fit entirely in GPU VRAM.
The default table shows memory, estimated generation speed, fit type, and
published date. Speed is colored by practical usability: under 4 tok/s is red,
4-10 is yellow, 10-30 is green, and 30+ is bright green. ~ / ? still mark
estimate confidence.
Fitting a model into your VRAM is the easy part. The hard part is knowing which of the models that fit is actually the best — and that is what whichllm is built to get right.
direct / variant / base / interpolated / self-reported and
discounted by confidence. Fabricated uploader claims and cross-family
inheritance (a small fork borrowing its much larger base's score) are
actively rejected.whichllm prints the answer; add
--json | jq for pipelines. No TUI, no keybindings to memorize.whichllm run downloads and starts a chat session instantlywhichllm snippet prints ready-to-run Python for any modelwhichllm --gpu "RTX 4090"--gpu, use commas, or write 2x RTX 4090--gpu-only / --fit full-gpu hides offload candidates--speed usable|fast hides slow rows by threshold--markdown / -m prints pasteable GFM tables--vram-headroom and --ram-budget avoid edge fitswhichllm plan "llama 3 70b"whichllm --jsonTry any model with a single command. No manual installs needed — whichllm
creates an isolated environment via uv, installs dependencies, downloads the
model, and starts an interactive chat.

# Chat with a model (auto-picks the best GGUF variant)
whichllm run "qwen 2.5 1.5b gguf"
# Auto-pick the best model for your hardware and chat
whichllm run
# CPU-only mode
whichllm run "phi 3 mini gguf" --cpu-only
Works with all model formats:
- GGUF — via llama-cpp-python (lightweight, fast)
- AWQ / GPTQ — via transformers + autoawq / auto-gptq
- FP16 / BF16 — via transformers
Get a copy-paste Python snippet instead:
whichllm snippet "qwen 7b"
from llama_cpp import Llama
llm = Llama.from_pretrained(
repo_id="Qwen/Qwen2.5-7B-Instruct-GGUF",
filename="qwen2.5-7b-instruct-q4_k_m.gguf",
n_ctx=4096,
n_gpu_layers=-1,
verbose=False,
)
output = llm.create_chat_completion(
messages=[{"role": "user", "content": "Hello!"}],
)
print(output["choices"][0]["message"]["content"])
# Auto-detect hardware and show best models
whichllm
# Simulate a GPU (e.g. planning a purchase)
whichllm --gpu "RTX 4090"
whichllm --gpu "RTX 5090"
# Specify variant
whichllm --gpu "RTX 5060 16"
# Override detected iGPU/unified-memory limits
whichllm --vram 8 --ram-bandwidth 68
# Simulate multiple GPUs
whichllm --gpu "2x RTX 4090"
whichllm --gpu "RTX 4090" --gpu "RTX 3090"
whichllm --gpu "RTX 4090, RTX 3090"
# Only show models that fit entirely in GPU VRAM
whichllm --gpu-only
whichllm --fit gpu
whichllm --fit full-gpu
# Avoid edge fits and background-RAM surprises
whichllm --vram-headroom 1.5GB
whichllm --ram-budget available
whichllm --ram-budget 8GB
# CPU-only mode
whichllm --cpu-only
# More results / filters
whichllm --top 20
whichllm --details # show Downloads metadata instead of runtime columns
whichllm --speed usable # minimum 10 tok/s
whichllm --speed fast # minimum 30 tok/s
whichllm --min-speed 4 # exact tok/s floor
whichllm --markdown # pasteable GitHub-Flavored Markdown table
whichllm --profile coding
whichllm --context-length 64k
whichllm --quant Q4_K_M
whichllm --min-speed 30 # exact tok/s floor
whichllm --evidence base # allow id/base-model matches
whichllm --evidence strict # id-exact only (same as --direct)
whichllm --direct
# JSON output
whichllm --json
# Force refresh (ignore cache)
whichllm --refresh
# Show hardware info only
whichllm hardware
# Plan: what GPU do I need for a specific model?
whichllm plan "llama 3 70b"
whichllm plan "Qwen2.5-72B" --quant Q8_0
whichllm plan "mistral 7b" --context-length 32768
# Upgrade: compare your current machine against candidate GPUs
whichllm upgrade "RTX 4090" "RTX 5090" "H100"
whichllm upgrade "Apple M4 Max" --top 5
# Run: download and chat with a model instantly
whichllm run "qwen 2.5 1.5b gguf"
whichllm run # auto-pick best for your hardware
# Snippet: print ready-to-run Python code
whichllm snippet "qwen 7b"
whichllm snippet "llama 3 8b gguf" --quant Q5_K_M
Markdown output is intended for GitHub issues, READMEs, Slack, Discord, and blog posts:
whichllm --markdown
whichllm -m --top 5 --gpu "RTX 4090"
JSON model rows include fit_type, vram_required_bytes,
vram_available_bytes, uses_multi_gpu, multi_gpu_effective_vram_bytes,
estimated_tok_per_sec, speed_confidence, speed_range_tok_per_sec,
speed_notes, benchmark_source, and benchmark_confidence. The speed range
is a planning range, not a live benchmark.
Use JSON output to feed scripts that map HuggingFace IDs to your local Ollama model names:
# Pick the top HuggingFace model ID
whichllm --top 1 --json | jq -r '.models[0].model_id'
# Find the best coding model ID
whichllm --profile coding --top 1 --json | jq -r '.models[0].model_id'
Ollama model names do not always match HuggingFace repo IDs, so a small mapping
step is usually needed before ollama run.
Add to your .bashrc / .zshrc:
alias bestllm='whichllm --top 1 --json | jq -r ".models[0].model_id"'
# Usage: ollama run $(bestllm)
Each model gets a 0-100 score. Benchmark quality and size form the core; evidence confidence and runtime fit then scale it, with speed, source trust, and popularity as adjustments.
| Factor | Effect | Description |
|---|---|---|
| Benchmark quality | core | Merged LiveBench / Artificial Analysis / Aider / Vision / Arena ELO / Open LLM Leaderboard, weighted by source confidence |
| Model size | up to 35 | log2-scaled world-knowledge proxy (MoE uses total params) |
| Quantization | × penalty | Lower-bit quants discounted multiplicatively |
| Evidence confidence | ×0.55–1.0 | none / self-reported ×0.55, inherited ×0.78, direct full |
| Runtime fit | ×0.50–1.0 | partial-offload ×0.72, CPU-only ×0.50 |
| Speed | -8 to +8 | Usability gate vs a fit-dependent tok/s floor; reported with confidence and range metadata |
| Source trust | -5 to +5 | Official-org bonus, known-repackager penalty |
| Popularity | tie-breaker | Downloads/likes; weight shrinks as evidence strengthens |
Score markers:
- ~ (yellow) — No direct benchmark; score inherited/interpolated from the model family
- !sr (bright yellow) — Uploader-reported benchmark only, not independently verified
- ? (red) — No benchmark data available
Speed display:
- red — Slow generation speed (<4 tok/s)
- yellow — Marginal generation speed (4-10 tok/s)
- green — Usable generation speed (10-30 tok/s)
- bright green — Fast local generation speed (>=30 tok/s)
- ~ (yellow) — Estimated tok/s range is available
- ? (red) — Low-confidence speed estimate; backend/runtime sensitivity is high
image-text-to-text) when `--profil$ claude mcp add whichllm \
-- python -m otcore.mcp_server <graph>