Part of Running LLMs on Your Own Hardware: From “Will It Even Fit” to a Model That Does Your Work — running large language models on your own hardware.
04_lms_cli_qwen.py
LM Studio CLI on Windows 11 is a feature many LM Studio users never touch. Yet for anyone running benchmarks, testing several models in a row, or wiring local LLMs into their own scripts, the CLI is the foundation. This article covers every key lms command, the parameters that matter, and how to automate model management without opening the GUI once. Every command output below is captured from a real session, and the CLI step timings and inference throughput are measured — Qwen3.5-2B Q4_K_M, n=10 runs per step, mean ± std, no estimates.
lmsreplaces the GUI for downloading, loading, and serving models.- The full loop — list, load, serve, unload — is scriptable in a few lines.
- New model architectures may need a one-line runtime update before they load.
- After
lms load, the OpenAI-compatible server is live on port 1234. - Real measurement (n=10):
lms loadon Qwen3.5-2B averages 7.0s ± 0.5s; the model itself generates 20.7–28.5 tok/s depending on prompt type.
Why the CLI beats the GUI for real work
The GUI is fine for a first chat. It falls apart the moment you repeat yourself. Testing five models means five rounds of clicking through download, load, and unload dialogs, and no record of what you did. The CLI turns that into a script you can rerun, share, and version.
Three benefits stand out. First, reproducibility: a script sets the same context length and GPU offload every time, so results are comparable. Second, automation: you can queue an overnight sweep across many models and wake up to a results file. Third, integration: the CLI slots into CI, into Python, and into a headless server where no desktop exists. For benchmarking, those three properties are not nice-to-haves — they are the whole point.
What lms is and where to find it
LM Studio ships a CLI tool called lms. The installer places it under your user profile and wires it onto PATH, so on a standard Windows 11 install you can call it from any terminal. The binary lives here:
%USERPROFILE%.cachelm-studiobinlms.exe
Verify it, then note one important quirk: the CLI needs the LM Studio background service running. If a command hangs on “Waking up LM Studio service”, launch the LM Studio app once to start the service, then retry.
lms version
lms server start # -> Success! Server is now running on port 1234
lms command map — cheat sheet

| Command | What it does |
|---|---|
lms --version | CLI version |
lms ls | List local models |
lms ls --json | List in JSON format (for scripts) |
lms server start | Start API server (port 1234) |
lms server stop | Stop server |
lms server status | Server status |
lms get ORG/REPO@QUANT | Download model from HuggingFace |
lms load ORG/REPO@QUANT | Load model into server |
lms unload | Unload active model |
lms unload --all | Unload all models |
lms rm ORG/REPO | Delete model from disk |
lms ps | Running models |
lms log stream | Live server logs |
The most-used command is lms ls. It groups models by type and marks which one is loaded. Here is a real listing from a working machine:
$ lms ls
You have 3 models, taking up 30.41 GB of disk space.
LLM PARAMS ARCH SIZE DEVICE
google/gemma-4-12b-qat (1 variant) 12B gemma4 7.15 GB Local ✓ LOADED
qwen3.6-35b-a3b-mtp 35B-A3B qwen35moe 23.17 GB Local
EMBEDDING PARAMS ARCH SIZE
text-embedding-nomic-embed-text-v1.5 Nomic BERT 84.11 MB
Notice how the output separates LLMs from embedding models and shows the exact architecture. That detail matters, because the architecture decides whether your current runtime can load the model at all — as the next section shows.
A more recent real session, after downloading the small model used for the benchmarks in this article:
$ lms ls
You have 2 models, taking up 2.03 GB of disk space.
LLM PARAMS ARCH SIZE DEVICE
qwen3.5-2b 2B qwen35 1.94 GB Local
EMBEDDING PARAMS ARCH SIZE DEVICE
text-embedding-nomic-embed-text-v1.5 Nomic BERT 84.11 MB Local
Downloading Qwen models via CLI
Any GGUF model from HuggingFace is downloaded via lms get. The full ID consists of organisation, repository name, and quantization after a colon:
# Qwen3.6-35B-A3B in Q4_K_M quantization (~32 GB)
lms get lmstudio-community/Qwen3.6-35B-A3B-GGUF@Q4_K_M
# Qwen3-0.6B — lightweight model for drafter/agent
lms get lmstudio-community/Qwen3-0.6B-GGUF@Q4_K_M
# Qwen3-VL 7B — vision model
lms get lmstudio-community/Qwen3-VL-7B-Instruct-GGUF@Q4_K_M
Always check free disk space before downloading. LM Studio does not do this automatically:
Free ebook
Free AI Video, Generated Locally
Working scripts and measured benchmarks. Free.
No spam. Unsubscribe at any time.
# PowerShell — free GB on drive C:
[math]::Round((Get-PSDrive C).Free / 1GB, 1)
Loading with parameters — complete option list
The lms load command accepts several important parameters:
lms load lmstudio-community/Qwen3.6-35B-A3B-GGUF@Q4_K_M `
--context-length 8192 `
--gpu max
What the parameters mean:
--context-length 8192— context window size in tokens. Larger = more VRAM (KV-cache). Qwen3.6 natively supports up to 262K tokens, but with Q4_K_M on 48 GB VRAM safely up to 32K.--gpu max— offload all layers to GPU. You can also pass an integer (e.g.40) = how many layers to GPU, rest to CPU.
lms get, but once a model is downloaded, lms load may reject that same identifier with Cannot find a model matching the provided model key and drop into an interactive picker — which hangs any non-interactive script. Use the short key from lms ls or lms ps instead (e.g. lms load qwen3.5-2b, not lms load lmstudio-community/Qwen3.5-2B-GGUF@Q4_K_M). Always test the exact load command interactively once before wiring it into an unattended script.
lms load. MTP requires loading a separate GGUF model variant (e.g. qwen3.6-35b-a3b-mtp). On AMD gfx1100 (RDNA3), this MTP variant currently fails to load with Error: Failed to load model in LM Studio.
Qwen3.6-35B-A3B-UD-Q4_K_S) loads and runs correctly via llama-server with --spec-type draft-mtp --spec-draft-n-max 4 on AMD gfx1100 (RDNA3, Vulkan). Real benchmark on AMD PRO W7900: baseline 49.7 tok/s → MTP 91.8 tok/s (1.85× speedup). See Multi-Token Prediction on AMD W7900 for the full methodology and results.
Updating the runtime for new model architectures
Here is a real gotcha the CLI makes easy to fix. A brand-new architecture can refuse to load on an older engine, and the error is unhelpfully terse:
$ lms load google/gemma-4-12b-qat --gpu max
Error: Failed to load model.
(X) CAUSE Failed to load model
The cause is not memory and not the model file. LM Studio runs on a bundled llama.cpp engine, and a fresh architecture like gemma4 needs a newer engine build than the one installed. The lms runtime commands manage exactly this. First check what is available:
lms runtime ls # list installed engines
lms runtime update --yes # pull the newest compatible engine
On the test machine, the update bumped the Vulkan engine from 2.11.0 to 2.24.0. After that, the same load command succeeded in seconds:
$ lms load google/gemma-4-12b-qat --gpu max --context-length 8192
Model loaded successfully in 22.11s.
So when a new model will not load, do not assume the file is broken. Update the runtime first. This single step saves a lot of guesswork, and it is invisible in the GUI unless you know to look for it.
Multi-model test sequence — automation

Testing several models in a row without a GUI is a sequence: download → load → test → unload → (optionally) delete. In PowerShell:
$models = @(
"lmstudio-community/Qwen3.6-35B-A3B-GGUF@Q4_K_M",
"lmstudio-community/Mistral-Small-3.1-24B-Instruct-2503-GGUF@Q4_K_M",
"lmstudio-community/gemma-3-27b-it-GGUF@Q4_K_M"
)
foreach ($model in $models) {
Write-Host "=== Testing: $model ===" -ForegroundColor Cyan
lms get $model
lms load $model --context-length 8192 --gpu max
python run_my_benchmark.py
lms unload --all
$freeGB = [math]::Round((Get-PSDrive C).Free / 1GB, 1)
Write-Host "Free disk space: $freeGB GB"
if ($freeGB -lt 15) {
Write-Host "Low disk space — removing model" -ForegroundColor Yellow
lms rm ($model.Split("@")[0])
}
}
Python does the same more elegantly — the LMSManager class from the repository handles all these steps automatically, including asking for confirmation before deleting a model.
Verification via REST API after loading
After lms load the server is available on port 1234. Verification in PowerShell:
# List loaded models
Invoke-RestMethod http://localhost:1234/v1/models | ConvertTo-Json
# Quick inference test
$body = @{
model = "local-model"
messages = @(@{role="user"; content="Reply in one sentence."})
max_tokens = 50
} | ConvertTo-Json
Invoke-RestMethod -Uri http://localhost:1234/v1/chat/completions `
-Method POST -ContentType "application/json" -Body $body
To see what is loaded and how much context it holds, use lms ps. The real output confirms the model, its context window, and its idle state:
$ lms ps
IDENTIFIER MODEL STATUS SIZE CONTEXT DEVICE
google/gemma-4-12b-qat google/gemma-4-12b-qat IDLE 7.15 GB 8192 Local
Real benchmark: how fast is the CLI itself?
Every number below comes from a dedicated benchmark script that drives lms the same way a scripted overnight sweep would: unload, load, check status, run inference, unload again — 10 times per step, model Qwen3.5-2B Q4_K_M, context 4096, full GPU offload. Diagram 1 (above) plots the same data.
| Step | Mean | Std dev | n |
|---|---|---|---|
lms server status | 0.93 s | ± 0.06 s | 10 |
lms ls | 1.08 s | ± 0.19 s | 10 |
lms load qwen3.5-2b (ctx 4096, GPU max) | 7.03 s | ± 0.48 s | 10 |
lms ps | 1.13 s | ± 0.05 s | 10 |
lms unload --all | 1.19 s | ± 0.12 s | 10 |
Download and lms rm are intentionally excluded from this table — they depend on network speed and NVMe write speed, not on the CLI, so averaging them here would misrepresent what the tool itself costs. The one number worth remembering: a cold lms load on a small model is a ~7-second tax per cycle, which matters if your sweep script loads and unloads dozens of times overnight.
Inference throughput, same model, streamed via the OpenAI-compatible endpoint, n=10 per prompt category:
| Prompt category | Throughput | TTFT |
|---|---|---|
| Short code (≤300 tok) | 20.7 ± 0.4 tok/s | 2396 ± 58 ms |
| Medium reasoning (≤500 tok) | 28.5 ± 0.2 tok/s | 2422 ± 39 ms |
| Long generation (≤800 tok) | 26.9 ± 1.0 tok/s | 2341 ± 64 ms |
TTFT sits around 2.3–2.4 seconds regardless of prompt size — on this machine that is mostly prompt-processing overhead for the small system+user prompt, not something that scales with the requested output length. Throughput is lower for the shortest prompt, which is expected: with fewer tokens to generate, a larger share of the request time is spent on the fixed per-request overhead rather than steady-state decoding.
Log monitoring during model loading
While loading a large model (e.g. 32 GB) it is worth watching the logs to detect OOM errors or HIP backend issues:
# In a separate terminal — live logs
lms log stream
# Filter for errors only
lms log stream | Select-String -Pattern "error|warning|failed"
Common errors and fixes
| Error | Cause | Solution |
|---|---|---|
lms: not recognized | lms not in PATH | Add %LOCALAPPDATA%ProgramsLM-Studio to PATH |
out of memory on load | Insufficient VRAM or RAM | Reduce context length or use a lower quantization |
model not found | Wrong model ID | Check lms ls — exact name from the local list |
| MTP not working | Model has no MTP head in GGUF | Use Qwen3 or DeepSeek-V3 models; fallback: 01b_mtp_rocm.py |
| Server won’t start | Port 1234 in use | netstat -ano | findstr :1234 → kill PID |
Full session — from zero to benchmark
# 1. Start server
lms server start
# 2. Check what you have locally
lms ls
# 3. Download Qwen3.6 if missing
lms get lmstudio-community/Qwen3.6-35B-A3B-GGUF@Q4_K_M
# 4. Load with full GPU offload
lms load lmstudio-community/Qwen3.6-35B-A3B-GGUF@Q4_K_M `
--context-length 8192 --gpu max
# 5. Run benchmark
python 01_mtp_benchmark.py --no-download
# 6. Unload
lms unload --all
# 7. Check results
python 02_analyze_results.py
Scripting the CLI from Python
The CLI shines inside automation. Because every command is deterministic and returns clean text, you can drive it from Python with subprocess and parse the results. The pattern below loads a model, runs a benchmark, and unloads it, so an overnight job can sweep a whole model list unattended.
import subprocess
def run(cmd: str) -> str:
return subprocess.run(cmd, shell=True, capture_output=True, text=True).stdout
run("lms load google/gemma-4-12b-qat --gpu max --context-length 8192")
# ... hit http://localhost:1234/v1/chat/completions and record metrics ...
run("lms unload --all")
This is how the benchmark scripts in this series stay reproducible. They never depend on a human clicking through the GUI, so the same run produces the same setup every time. For a shared workstation, that repeatability is the difference between a trustworthy benchmark and a one-off anecdote.
Frequently asked questions
Where is the lms binary on Windows?
It installs under %USERPROFILE%.cachelm-studiobinlms.exe and is added to PATH by the installer. If lms is not recognised, reopen your terminal or add that folder to PATH manually.
Why does an lms command hang on “Waking up LM Studio service”?
The CLI needs the LM Studio background service. Launch the LM Studio app once so the service starts, then rerun the command. This is the most common first-time snag.
A new model fails to load — is the file corrupt?
Usually not. A new architecture often needs a newer engine. Run lms runtime update --yes, then load again. Only after the runtime is current should you suspect the file.
Can I run lms with no GUI at all?
Yes, once the service is running. The full loop — get, load, ps, unload — works headless, which is exactly what you want on a remote or shared box.
How do I free VRAM after a batch job?
Call lms unload --all. Loading a model reserves VRAM until you unload it, so releasing it between jobs keeps the GPU available for the next task.
Summary
LM Studio CLI is the tool that transforms your workflow from “clicking through the GUI” to “run a script and grab a coffee”. For benchmarking multiple models, testing MTP configurations, and integrating with your own Python pipelines — the CLI is essential. The demo script 04_lms_cli_qwen.py walks through every step and prints each command with its output — ready to screenshot for your own documentation. On this machine, with Qwen3.5-2B Q4_K_M, a full unload→load→inference→unload cycle costs about 9–10 seconds of pure CLI overhead on top of whatever the model itself generates — small enough to not think about, and reproducible enough to trust in an unattended sweep.
Companion code — every script and benchmark from this series lives in one repository: github.com/bestin-it/qwen-local-ai-scripts.
Free ebook
Free AI Video, Generated Locally
Run Wan 2.1 in ComfyUI on your own GPU — the scripts I use, measured times, sample clips. No cloud, no API keys.
No spam. Unsubscribe at any time.


Leave a Reply