Field notes · local LLMs on consumer hardware

Local AI from a Hardware Stash

Spare hardware, one mini PC, four local AI chips. Claude Code plans, delegates and checks; local models do the bulk work, so Claude usage goes to the work that needs it. 30+ models from a dozen labs went through the same automated tests: here is the winner for each chip, and every number behind it.

Contents

Claude Code orchestrates; local models on spare hardware take the bulk, checkable work (scripts, log reading, screen reading, first-pass reviews), so Claude usage goes to the decisions. Every model below ran the same automated tests on a real production web app's code, pinned at one commit.

The short version#

A mini PC and two external GPUs from a hardware stash give five chips: the Ryzen CPU runs the scripts the models write, and the other four each run a local AI model. More than 30 models from a dozen labs, and ten inference engines (see Engines compared), competed for them on the same tests. Here is who won each chip and why; every number is backed by the full results further down.

Chip Job Winner Why (measured) Beat
RTX 5060 Ti 16 GB (OCuLink) Fast tier: bulk jobs, scripts, unit tests, screenshots Gemma 4 26B-A4B ~200 tok/s; 70/80 seeded bugs (77 with a 2K thinking budget); 7/9 unit tests; reads screenshots 10 other models
Radeon 890M iGPU (shares system RAM) Best tier: careful reviews, screen reading Qwen3.6-35B-A3B, 4-bit 71/80 bugs; screen reading 0.968 (tied best); ~25 tok/s 3 other models
RX 7600 8 GB (USB4) Third opinion in bug hunts Ornith-1.5-9B, thinking capped at 1,024 tokens, with its DFlash drafter 66/80 bugs; 6/9 unit tests; the best overall score that fits in 8 GB; ~95 tok/s with the drafter (was ~38) 6 other models
XDNA2 NPU (in the Ryzen chip) Background script jobs (in reserve) Qwen3.6-35B-A3B (FastFlowLM) 20/23 scripts at ~18 tok/s; the only NPU model good enough to trust with scripts 7 other models
RTX 5060 Ti, deep mode (bonus round) Deep tier: long prompts, whole-commit reviews, background and overnight jobs Muse Glimmer 30B (Meta), medium reasoning 24/24 and 78/80 seeded bugs (80/80 at low reasoning); the only local model that caught a real review blocker; 64K context on the GPU alone 9 other models

Gemma and Qwen3.6 miss different bugs: together they find 74 of 80. Newest win: a 0.77 GB draft model made the RX 7600's third opinion about 2.5× faster with the same answers. Claude Code stays the orchestrator and makes the final call on every review (see the deep tier's real-commit test below).

Does this hybrid AI harness (Claude Code orchestrating, local models on the home PC's chips, scripts on the CPU) really save Claude tokens? Measured over four days of real work: a modest, real saving of about 1.3% of what Claude reads, mostly from reading screenshots and big files. Scripts on the CPU saved several times more, and a 16 GB GPU mainly buys speed (see "Does a hybrid AI harness really save Claude tokens?" below).

Terms used on this page
  • tok/s: tokens per second, the speed of the output (a token is about three-quarters of a word).
  • Prompt reading vs writing (pp / tg): pp = reading the prompt, tg = writing the answer; pp512 / tg128 = a 512-token prompt and 128 written tokens.
  • MoE (mixture of experts): a model split into many "experts", only a few of which run per token, so a big model is cheap to run.
  • Expert offload (-ncmoe N): keeps the experts of N layers in system RAM instead of GPU memory, so models bigger than the GPU still run.
  • Speculative decoding (MTP, DFlash, EAGLE3): a small helper guesses the next tokens and the main model checks them: faster output, same result.
  • Quantization (Q4_K_XL, IQ2_XS, IQ3_XXS…): storing weights in fewer bits to shrink a model; the number is roughly bits per weight.
  • GSQ-RCO: a compression method from IST Austria used for several builds here; the "Coder" build also drops half the experts, chosen for code.
  • Thinking budget / effort: a cap on how many reasoning tokens a model may spend before answering; "low" and "xhigh" are effort presets.
  • Seeded bugs (24- and 80-item sets): bugs deliberately planted in the app's real code; the score is the share found.
  • Mutation killing: unit tests must pass on the real code and fail on deliberately broken copies.
  • eGPU / OCuLink / USB4: external GPU connections; OCuLink here is a PCIe 4.0 x4 link, a quarter of a desktop x16 slot.
  • Tiers: fast (NVIDIA card), best (iGPU), third opinion (RX 7600), deep (the strongest reviewer, swapped onto the NVIDIA card on demand).

The hardware#

Part What Role here
CPU AMD Ryzen AI 9 HX 470 Runs the generated analysis scripts in a sandbox; MoE expert offload
RAM 64 GB DDR5-4800 SO-DIMM; the OS sees 59.4 GiB; about 48 GB/s measured Shared by the iGPU and by offloaded model experts
GPU 1 NVIDIA RTX 5060 Ti 16 GB, eGPU over OCuLink (PCIe 4.0 x4) Fast tier: Gemma 4 26B at about 200 tok/s
GPU 2 AMD Radeon 890M iGPU, borrows up to about 30 GiB of system RAM "Best" tier: Qwen3.6-35B 4-bit at about 25 tok/s, plus embeddings
GPU 3 AMD Radeon RX 7600 8 GB, eGPU over USB4 (added 2026-10-18) Third opinion in bug hunts: Ornith-1.5-9B with thinking capped at 1,024 tokens, always on with its 0.77 GB DFlash drafter (~95 tok/s; ~32–38 without it). It needs amdgpu.runpm=0, and services are pinned to a GPU by PCI id
NPU AMD XDNA2 (8 columns, fw 1.1.2.64) FastFlowLM 1.0.9: Qwen3.6-35B-A3B at about 18 tok/s, 20 of 23 script tasks; candidate for script jobs
Disk 1 1 TB NVMe (WD SN740), about 4.7 GB/s direct reads System, plus every model that loads fully into GPU or NPU memory
Disk 2 1 TB NVMe (Samsung 9100 PRO, a PCIe 5 drive in a PCIe 4 x4 slot), about 7.2 GB/s direct reads (added 2026-10-18) Models bigger than RAM, whose experts stream from disk while decoding (GLM-5.3-Flash, DeepSeek-V4-Flash, GLM-5.2)

OS: Ubuntu 26.04 with kernel 7.0, llama.cpp prebuilt CUDA and Vulkan builds. Details, memory notes and patches are further down.

Memory budget, bandwidth and goals

Memory available to the tests. 64 GB installed doesn't mean 64 GB usable:

GiB
Installed (SO-DIMM) 64.0
Reserved for the iGPU frame buffer (UMA carve-out, set in BIOS) −2.0
Firmware and kernel reservations about −2.6
Seen by the OS 59.4
Docker app stack running alongside (10 containers, idle) about −0.2
AMD-tier Qwen Q4 when loaded (lives in system RAM via GTT) about −22

Notes:

  • Docker isn't the cause: idle containers barely register. The big competitor is the AMD-tier model, because an iGPU's "VRAM" is ordinary system RAM. It was stopped to free about 22 GB (leaving roughly 55–57 GiB) for the GLM-5.3-Flash -ncmoe sweeps and evals, and for the 44 GB GLM-5.2 run. The other GLM-5.2 runs (CPU, and CUDA with 28 GB) had it loaded.
  • Lowering the carve-out: setting the UMA frame buffer to its BIOS minimum would recover up to about 2 GiB. The iGPU allocates through GTT anyway.

Memory speed.

  • Older and slower than the platform's limit: the modules are DDR5-4800. The amdgpu driver's top memory clock is 2400 MHz (DDR: 4800 MT/s), and the kernel detects DDR5 SPD hubs on both SO-DIMMs. The HX 470 supports DDR5-5600 on SO-DIMMs.
  • Theoretical peak: 2 channels × 8 bytes × 4800 MT/s = 76.8 GB/s.
  • Measured (STREAM-style triad, 24 threads): about 48-49 GB/s idle (copy ~43 GB/s; same at 8, 12 and 24 threads), about 63% of the 76.8 GB/s theoretical; 47 GB/s with a RAM-offloaded model running.
  • Why it matters: RAM bandwidth caps every run that keeps model weights or experts in system RAM: the AMD iGPU tier, the CPU parts of MoE offload, and GLM. For example, GLM-5.3-Flash at IQ2 reads several GB of experts per token. DDR5-5600 would add about 17% bandwidth; LPDDR5X-8000 machines (Ryzen AI Max) have about 3× more.

Goal: offload bulk, low-stakes coding work on a real production web app: extraction, first-pass review, drafts, screenshot triage from Claude to local models, measured for both speed and quality of output.

Exploration window: 2026-10-15 to 2026-10-19 (new hardware from the evening of 2026-10-18).

The contenders#

More than 30 models from a dozen labs, in GGUF builds from the labs themselves and from community quantizers (Unsloth, bartowski, IST Austria's GSQ-RCO, UkisAI, kunthawat):

"Beat N other models" below counts distinct models (not quantizations or settings) that ran on that chip.

How every model was tested#

Test Size What it checks
Seeded bugs 80 (+ a 24-item set) bugs planted in the app's real code (frontend and backend): can it find them?
Script tasks 23 write an analysis script that runs in a sandbox and gives the right answer
Unit-test tasks 9 write tests that pass on the real code and catch deliberately broken copies
App screenshots 20 read every heading, button and label of a real page exactly
Speed tok/s measured on this hardware: a slow model costs time on every job

Everything is scored automatically by scripts, from the same pinned commit, so scores stay comparable across days; no Claude tokens are spent judging.

The full test suite and scoring

How models are compared:

  • An eval script runs project-grounded tasks, each auto-scored from 0 to 1, with no Claude tokens spent judging.
  • Inputs come from the app's source, pinned at one fixed commit so scores stay comparable across days.
  • A matrix script runs a list of configs unattended, one after another.
  • The tables below are regenerated by a report script after every batch.
Category Task Scoring
endpoints JAX-RS class → METHOD /path list F1 vs codemap facts
apicalls React page → xxxApi.method calls F1 vs a regex over the source
json file → strict JSON {purpose, exports} valid JSON, plus F1 on exports
codegen 5 small TS functions hidden tests run with bun
codehard 4 harder TS functions (score conversion, RFC 4180 CSV, interval merge, 1224 ranking) per-case tests
bugspot one injected operator bug, 80-line window line ±1
bughard one subtle bug (nullish, boolean, .some vs .every, off-by-one), 160-line window line ±1
Settings that matter: thinking budgets, speculative decoding, quantization bits

Effort levels: bounded thinking helps; unbounded or tiny budgets hurt. On the 80-item set:

model thinking off budget 256 budget 1,024 unbounded
Gemma 4 26B (NVIDIA) 0.875 (1.5 min) 0.713 0.912 (10 min) 0.05 (runs out at 4K)
Qwen3.6 Q4 (iGPU) 0.887 (7 min) 0.850 0.912 (57 min) 0.800 (2.5 h)
  • A request can set the budget itself with "thinking_budget_tokens": N (llama.cpp; the server-wide equivalent is --reasoning-budget N).
  • The harness exposes this as local_ask effort="high", which means thinking capped at 1,024 tokens.

Unbounded thinking hurts, and more bits don't help. On the 80-item set:

  • Thinking takes the iGPU model from 0.887 to 0.800, and from 7 min to 2.5 h.
  • Gemma's thinking over-deliberates until it hits the token budget, scoring 0.05 at 4K tokens; that's not a parser bug.
  • On the iGPU, Q5_K_S and MXFP4_MOE both score 0.875 against 0.887 for Q4_K_XL: quality saturates at 4-bit.
  • Gemma's MTP draft length is best at the default 3 (171 / 161 / 189 tok/s on code, summary and JSON). Longer drafts only pay on JSON.

MTP speculative decoding is the biggest win, and it's in production. The Unsloth Qwen3.6-35B-A3B-MTP-GGUF running with --spec-type draft-mtp decodes at about 196 tok/s against 104 without it. Draft acceptance runs 70–92%, at the same or better quality (0.879 → 0.919 on the easy suite).

  • The MTP head costs VRAM, so llm-nv-main now runs 2 slots × 32K, and the vision encoder runs on the CPU (--no-mmproj-offload). An image still takes about 9 s.
  • On the GPU, the vision encoder hit OOM at every context size tried, down to 40K.
  • 99% of real prompts are under 7K tokens (from the router's usage log). The router now skips a backend when a prompt exceeds its max_prompt, so prompts over 30K go to the AMD 64K slots.

Newer llama.cpp (b11706, 64 commits later, including a Vulkan KV-cache change for AMD) gave no real gain. On the same prompts and production configs:

  • iGPU: 23.4 tok/s decode on both builds.
  • NVIDIA: 146 tok/s decode on both; prompt reading 2,060 → 2,142 tok/s.
  • Production stays on the proven build.
  • MTP decode speed depends on content (146 tok/s on one prompt, about 196 on the eval tasks), so only compare configs on identical prompts.

ROCm on the 890M is no faster than Vulkan. This used llama.cpp's prebuilt ROCm build with Ubuntu 26.04's packages (sudo apt install libamdhip64-7 libhipblas3 librocblas5).

  • Ubuntu's rocBLAS has no kernels for the 890M's chip (gfx1150). HSA_OVERRIDE_GFX_VERSION=11.0.0 makes it run the gfx1100 kernels.
  • Production shape: 25.0 tok/s decode and 471 tok/s prompt, against Vulkan's 23.4 and 478.
  • Vulkan stays, since it needs no override.

N-gram speculative decoding (ngram-mod) gave no gain on these tasks: the outputs are short and don't copy the input. It may still help whole-file rewrites; not tested yet.

One countdown per chip#

The home setup has five chips. One, the Ryzen CPU, is reserved for running the scripts the models write; the other four each need the right AI model. So: four countdowns (third place, second place, the winner, and why), plus a bonus round for the NVIDIA card's deep mode.

NVIDIA RTX 5060 Ti 16 GB: the fast tier#

Full numbers for the NVIDIA card

The fast tier is now Gemma 4 26B-A4B QAT (UD-Q4_K_XL) with its MTP draft, replacing Qwen3.6-35B-A3B IQ3_XXS.

  • In the production shape (2 × 32K, vision on CPU) it scores higher: 0.894 against about 0.863 over 8 categories.
  • It finds more bugs: bugauto 0.792 against 0.708, and bugspot 1.0 against 0.6.
  • It's faster: on the same 5.5K prompt, 2,138 tok/s prompt against 1,892, at the same decode speed.
  • Vision is as accurate and 2.5× faster: 84 s for 20 pages against 206 s.
  • It loses only on codegen (0.8 against 1.0).
  • 2 × 32K at the default micro-batch loads, then runs out of VRAM on the first real request. -ub 256 fixes it, so test fit with a real long request, not /health.

CUDA beats Vulkan on the RTX 5060 Ti. Same llama.cpp build (b11706), Gemma 4 26B-A4B, -fa 1:

backend pp512 pp4096 tg128
CUDA 3,869 3,775 140
Vulkan 3,238 3,029 123

An 80-item seeded-bug set (bugbig, frontend and backend Java, separate seed) confirms the switch:

model bugbig (80) decode
Qwen3.6-35B-A3B Q4_K_XL + MTP (iGPU, best) 0.887 ~22 tok/s
Gemma 4 26B-A4B QAT + MTP (NVIDIA, new fast) 0.875 ~200 tok/s
Ternary-Bonsai-2-27B PQ2_0 (NVIDIA, PrismML fork) 0.800 ~48 tok/s
Nemotron-3.5-Bolt-74B-A9B "24GB" (iGPU) 0.688 ~11 tok/s
Qwen3.6-35B-A3B IQ3_XXS + MTP (NVIDIA, old fast) 0.662 ~196 tok/s
  • Ternary-Bonsai-2-27B (Qwen3.8-27B in ternary weights, 7.2 GB) needs PrismML's llama.cpp fork. It uses only 9.4 GB of VRAM at 2 × 32K and scores 0.877 on the full suite, so it's a strong pick for 8–12 GB cards. Here, Gemma is faster and better.
  • NVIDIA's official Nemotron-3.5-Bolt "24GB" GGUF prunes experts per layer. Builds before about b11706 can't load it (check_tensor_dims ... ffn_gate_inp).

gpt-oss-20b on the GPU (12.1 GB MXFP4, low effort): close to the fast tier, and as good at unit tests (7 of 9), with very fast prompt reading (~5,000 tok/s); 65 of 80 bugs and ~128 tok/s keep Gemma 4 (70 of 80, ~200 tok/s, plus vision) in the fast tier. Its EAGLE3 drafter added a modest 7% (138 tok/s).

New model: Meta's Muse Glimmer 30B (dense 29.6B with a vision encoder, August 2026, Apache-2.0), as Unsloth's UD-IQ3_XXS (13.1 GB) fully on the 16 GB card. At low reasoning strength it found all 80 of 80 seeded bugs — the first perfect score on this rig — plus 23 of 24 on the smaller set, 21 of 23 scripts and 6 of 9 unit tests (tied with Ornith-1.5-35B for the best of any big model here; Gemma 4 has 7). It always thinks, so it writes at ~30 tok/s, but its DFlash drafter nearly doubles that to ~57 tok/s (70% of drafted tokens accepted, same output). Screen reading 0.931, a step below the current tiers. The strongest bug hunter yet that runs on the GPU alone.

Qwen3.8-27B and its Swift 1.5 tune on the card alone:

  • Swift 1.5 Qwen3.8-27B IQ3_S + MTP (12.1 GB, fully on the 16 GB card, ~52-64 tok/s) on 10 seeded bugs: low effort found 9 of 10 in 7 minutes; the template's default xhigh found 8 in 16 minutes with twice the thinking (44K tokens); thinking off found 8 in 26 seconds. On this kind of bug hunt, xhigh bought nothing — low effort is the sweet spot, and thinking off is the fast path. The template's default really is xhigh.
  • Base Qwen3.8-27B vs Swift 1.5 on the same 10 bugs: at xhigh both found 8, and Swift needed 35% fewer thinking tokens (44K vs 68K; 16 vs 24 minutes) — close to the 42% UkisAI reports. At low effort the base model was the best option of all: 9 of 10 in 4 minutes with only 12K thinking tokens (Swift: 9 of 10, 22K tokens, 7 minutes). Thinking off: 8 of 10 in 26 seconds for both. Takeaway for a 16 GB card: use low effort for bug hunts, xhigh only when you've measured it helps, and Swift if you do run xhigh.
  • Swift 1.5 Qwen3.8-27B IQ3_XXS + MTP (10.4 GB) fits entirely on the 16 GB card with a 64K context: it found 12 of 12 functions in a 56K-token prompt in 83 seconds (reading at ~715 tok/s, writing at ~50 tok/s), and matched the larger IQ3_S on the bug sets (8 of 10 at xhigh and with thinking off). A strong long-context option that needs no RAM offload.
  • Full test suite, Swift 1.5 27B IQ3_XXS (10.4 GB, entirely on the 16 GB card, with vision): at low thinking effort it found 24 of 24 and 78 of 80 seeded bugs and wrote 22 of 23 scripts — matching the best scores on this rig (the 68 GB Flash-Next deep tier models need system RAM for the same scores), at ~64 tok/s instead of ~24. Screen reading 0.965, level with the current tiers. Thinking off it is quick and solid (0.840 suite, 72 of 80 bugs). Its one weak spot is writing unit tests (2.5 of 9), where the fast tier stays ahead (7). That run of 104 tasks took 38 minutes, so it suits careful review work rather than quick jobs.
  • Same test, base Qwen3.8-27B IQ3_XXS at low effort: 23 of 24 and 78 of 80 bugs, 23 of 23 scripts, in 39 minutes with about the same thinking (129K vs 127K tokens). So the jump comes from switching low-effort thinking on, not from the Swift fine-tune: any Qwen3.8-27B at IQ3_XXS gives a 16 GB card deep-tier accuracy at ~63 tok/s with no system RAM. Swift's edge shows at xhigh, where it thinks 35% less.
  • Community build of the same quant — kunthawat's Swift 1.5 27B IQ3_XXS (10.2 GB, Unsloth-style imatrix): as good as UkisAI's own file and a little better without thinking: 0.858 vs 0.840 on the suite, 74 vs 72 of 80 bugs, 22 vs 19 scripts. At low effort it found 23 of 24 and 78 of 80 with 23% less thinking (98K vs 127K tokens, 31 vs 38 minutes). Its author's 16 GB profile (one slot, 100K context, 4-bit KV cache) really fits: it found 12 of 12 functions in an 82K-token prompt in 2 minutes, all on the GPU.

Qwen3.8-27B now fits the fast tier's shape. IST Austria's GSQ-RCO IQ3_S with MTP built in (12.1 GB) serves 2 × 32K with the vision encoder on the CPU (-ub 256), and a real 26K-token prompt ran (read at 860 tok/s). Against Gemma 4: more bugs (0.925 against 0.875 on the 80-item set, 21 against 19 of 24), one more script (20), the same screenshot score (0.965, but 204 s against 84 s), far fewer test tasks (2 against 7 of 9), and about 60 tok/s against 200. It's a candidate for a switchable review mode, not the default.

Qwen3-Coder-30B-A3B (UD-Q3_K_XL) loses to Gemma 4 on every category we use (bugs 0.738 vs 0.875, scripts 17 vs 21, tests 3 vs 7) at half the decode speed (~106 tok/s).

LFM2.5-24B-A2B: rejected. It always reasons; neither enable_thinking=false nor reasoning_effort=low stops it, so at a normal token budget it never answers.

  • With a 3000-token budget it scores 0.591, finds almost no bugs, and wrote 134K tokens for the suite.

Liquid's small models: rejected. Both were run on the RTX 5060 Ti with llama.cpp on the same suite and screenshot set.

  • LFM2.5-1.2B-Instruct scores 0.198 at Q4_K_M and 0.134 at Q8_0. It wrote 0 of 23 scripts and 0 of 9 unit tests, scored 0.062 on the 80 seeded bugs, and only JSON output (0.84 at Q4_K_M) and the simple code tasks (0.45) are usable. It is fast, at ~448 tok/s on the 5060 Ti and ~218 on the RX 7600 (Vulkan), but speed does not make up for it.
  • LFM2.5-VL-1.6B reads screenshots at 0.436 in 32 s, against 0.965 for Gemma 4 and Qwen3.8-27B. It got the main heading right on only 25% of pages and found 10% of the buttons, and 3 of 20 answers did not parse.

Unit-test writing, scored by mutation killing. The model writes bun:test tests for 9 pure functions from the app. The tests must pass on the real code and fail on deliberately broken copies (15 mutants, after dropping one equivalent mutant a frontier model's tests also couldn't kill).

  • Gemma 4 (fast tier): 7 of 9 functions in 67 s, killing every mutant wherever its tests passed. Qwen3.6 Q4 on the iGPU: 3 of 9, in 680 s.
  • Every miss was a test with a wrong expectation, so it fails on the correct code. A real run can detect that without a reference answer, so execute-and-repair should recover most of these.

Radeon 890M iGPU: the best tier#

Full numbers for the iGPU

Long prompts cost speed, not accuracy, on the iGPU tier. A probe packs real source files into one prompt and asks which file defines each of 12 functions spread through it. Qwen3.6 Q4 on the iGPU (64K slots) found all 12 at 18K tokens (prompt read at 357 tok/s, 84 s in all) and at 55K tokens (187 tok/s, 3.6 min).

Ornith-1.5-35B-A3B (a Qwen3.5-MoE fine-tune) doesn't beat the current tiers. On the 5060 Ti (IQ3_XXS) it scores 0.723 without thinking; with a 2,048-token thinking budget it finds 0.887 of the 80 bugs and passes 19 scripts and 6 test tasks at 113 tok/s, close to Gemma 4 but not better (0.963 bugs, 21 scripts, 7 tests at max effort). On the iGPU (Q4_K_M) it scores 0.776 at 12 tok/s, against Qwen3.6's 0.878 at 22. Llama 3.1 8B, Mistral Nemo 12B and Ling 3.0 Tiny score 0.52–0.60; both DeepSeek-R1 distills are worse still (0.37–0.46) and slow.

Vision (local Qwen3.6 multimodal) for UI audits#

  • Triage only: about 30% of its UI findings were confirmed by deterministic probes (DOM measurement, axe).
  • No exact numbers: pixel and contrast claims from the model are filtered out in code, because scripts measure those.
  • Page context didn't help: adding the page's purpose to the prompt didn't improve precision.
  • Speed: one 1440p screenshot takes about 8–9 s. Moving the vision encoder to the CPU (to make room for MTP) didn't change that.
  • Reading the screen is reliable, judging it isn't. A second eval scores the model against facts read from the live DOM rather than by eye. Playwright saves each screenshot together with its h1, button and tab labels, table headers and all visible text. Across 20 admin pages, the 4-bit Qwen3.6 on the iGPU scored:
measure result
main heading exactly right 20/20
buttons and tabs found (recall) 0.88
table headers found (recall) 0.99
strings it listed that exist on the page (grounded) 1.00: no invented labels
time per page about 5 s
  • Comparing against <button> tags alone made it look like it invented labels. Those "extras" were real dropdowns, links, form labels and calendar day names, so grounding is checked against all visible text.
  • Card-style buttons are scored by their first line (the title, not the subtitle).
  • Use the vision model to report what a page shows. Verify any claim about what's wrong with a script.
  • The 3-bit NVIDIA model reads screens just as well (same scores, no invented labels), so the compression that hurts bug-finding doesn't hurt reading.
  • It's 2× slower per screenshot (about 10 s vs 5 s), because its vision encoder had to move to the CPU to make room for MTP.
  • Vision requests now go to the iGPU first, with NVIDIA as overflow.
  • MiniCPM-V 4.7 doesn't beat them.
    • 35B-A3B (IQ3_XS) on the iGPU: scores 0.939 (buttons 0.77) at 6.3 s per page, against Qwen's 0.968 at 5 s.
    • 1B on the CPU alone: uses 2.2 GB of RAM and no GPU, and scores 0.838. It gets every heading right and invents nothing, finds 91% of table headers but only 45% of buttons, at about 6 s per page. It's a usable zero-GPU option for identifying pages and columns, not for full UI inventories.

Radeon RX 7600 8 GB: the third opinion#

Full numbers for the RX 7600

RX 7600 (8 GB, USB4): Vulkan only. Ubuntu's rocBLAS has no gfx1102 kernels, so the ROCm build fails. On Vulkan, Llama 3.1 8B Q4 runs at 874 tok/s prefill and 49 tok/s decode; Qwen3.5 9B at 834 and 39.

Small models are no substitute for the fast tier; Ornith-1.5-9B with a thinking budget comes closest. With thinking capped at 1,024 tokens it scores 0.810, finds 18 of 24 seeded bugs, and passes 16 of 23 script tasks and 6 of 9 test tasks at 32 tok/s. Qwen3.5 9B with the same budget scores 0.773 (14 bugs, 17 scripts, 5 tests). Both need thinking: without it Ornith drops to 0.698. The full suite takes 55 minutes, about five times Gemma 4's wall time, so it's a slow third worker for background jobs on the otherwise idle RX 7600.

  • On the 80-item bug set Ornith-1.5-9B finds 0.825 at 35 tok/s, close to Gemma 4 (0.875) on an 8 GB card.

DFlash drafter: about 2.5× faster, same answers (2026-10-21). A community DFlash draft model distilled for Ornith-1.5-9B (audreyt/Ornith-1.5-9B-DFlash-GGUF, Q4_K_M, 0.77 GB) fits beside it in 8 GB (7.3 GB used at 16K context). On a 700-token code answer:

drafter draft tokens per step accepted decode
none — — 38 tok/s
DFlash 16 33% 41 tok/s
DFlash 8 71% 60 tok/s
DFlash 4 87% 92–97 tok/s

The suite score is unchanged (0.701 with the drafter, 0.698 without), as expected for speculative decoding. Shorter drafts win here: the small card's time goes to checking drafts, so fewer, likelier guesses pay off. The service now runs with --spec-type draft-dflash --spec-draft-n-max 4.

XDNA2 NPU (built into the Ryzen chip): background jobs#

Full numbers for the NPU

The NPU runs Qwen3.6-35B-A3B well enough to take script jobs. With FastFlowLM 1.0.9 it decodes at about 18 tok/s (the iGPU's best tier: ~22) and passed 20 of 23 script tasks, about as many as Gemma 4 (19 by default, 21 at max effort). It found fewer seeded bugs than the same model on the iGPU (15 vs 22 of 24) and prefills slowly (87 tok/s, so a 5K-token prompt takes about a minute). Moving script generation there would leave both GPUs free.

  • The other NPU models are slower and weaker: Llama 3.1 8B 0.535, gpt-oss 20B 0.407 (20 tok/s). Gemma 4 12B and Qwen3.5 9B first scored 0 on scripts and tests. With a 4,096-token limit Gemma 4 12B passed 16 of 23 scripts and 5 of 9 test tasks, but at about 7 tok/s. Qwen3.5 9B still failed: its long answers turn into runs of spaces. A probe showed neither model thinks on short prompts, so the thinking theory was wrong. Of the smaller NPU models, only Gemma 4 E4B is interesting: weak at finding bugs (4 of 24) but 6 of 9 test tasks and 15 of 23 scripts, reading prompts at 421 tok/s (Qwen3.6 on the NPU: 87). Qwen3 4B scored 0.594 and Phi-4-mini 0.352. Qwen3 8B thinks on every answer (80–450 s per bug item) and was stopped; other thinking models were skipped.

The NPU needs no PPA or DKMS on Ubuntu 26.04. FastFlowLM's Ubuntu 26.04 package needs only libxrt2 and libxrt-npu2 from Ubuntu's archive (kernel 7.0 ships amdxdna and the 1.1 firmware), plus an unlimited memlock limit.

NPU (AMD XDNA2, amdxdna driver, fw 1.1.2.64)#

  • Colibri: has an --xdna path, but it's experimental and Windows-only.
  • FastFlowLM 1.0.9 (working since 2026-10-18):
  • Install (root): apt install libxrt2 libxrt-npu2 libxrt-utils-npu ./fastflowlm_1.0.9_ubuntu26.04_amd64.deb. Ubuntu 26.04's own XRT packages are enough; no PPA, no DKMS on kernel 7.0.
  • Memlock: the NPU maps large buffers, so set memlock unlimited (pam limits) and LimitMEMLOCK=infinity for user@.service if it runs as a user service. flm validate reports the limit.
  • FLM_MODEL_PATH puts models on the data disk; flm serve <tag> -p <port> exposes an OpenAI-style /v1/chat/completions, and reports speeds in usage (prefill_speed_tps, decoding_speed_tps) rather than llama.cpp's timings.
  • The NPU kernels are closed source but free to use and redistribute unmodified (FastFlowLM's binary licence).
  • Measured decode: Qwen3.6-35B-A3B ~18 tok/s, gpt-oss 20B ~20, Llama 3.1 8B ~12, Qwen3.5 9B ~9, Gemma 4 12B ~6. Prefill 87–375 tok/s, far below the GPUs.

Bonus round: the RTX 5060 Ti's deep mode, the strongest reviewer for background jobs#

Real commits, verified claims. Seeded bugs are planted; real review blockers are subtle. Seven real commits from the app (four with a blocker that Claude reviewers had confirmed and fixed, three clean) went to the deep candidates with the same neutral prompt, and an independent Claude agent checked every bug claim against the code:

Model and setting Bug claims Verified real Blockers found (of 4) Time for 7 commits
Muse Glimmer 30B, medium reasoning (deep tier) 24 1 1, with the exact mechanism 20 min
Swift 1.5 Flash-Next IQ2_XS 25 1 (minor, in a check script) 0 (2 partly) 17 min
Qwen3.8-Flash-Next Coder IQ1_M 22 3 (stale code comments) 0 (1 partly) 19 min
Muse Glimmer 30B, low reasoning 24 0 0 (2 partly) 9 min

New challengers (2026-10-21), same tests:

Model / setup Speed Suite 24 bugs 80 bugs Real blockers (of 4)
Muse Glimmer 30B, medium (deep tier) ~52 tok/s — 24/24 78/80 1
Ornith-1.5-122B UD-IQ3_XXS (released 2026-10-16), experts in RAM 5–12 tok/s 0.806 21/24 72/80 0
Qwen3.8-27B UD-IQ4_XS, 60 layers on the GPU (the rest on the CPU), 64K, 4-bit KV (a popular 8 GB-card recipe) 9–16 tok/s 0.836 23/24 75/80 0
Best Strata run: Swift 1.5 Flash-Next IQ3_XXS (details below) 58 tok/s 0.863 23/24 77/80 0

The Strata engine (2026-10-21), every model it supports, same tests. Strata is a llama.cpp-based engine for MoE models that keeps the hottest experts in a GPU cache and drafts with the model's MTP layer. It supports the Qwen3.8-Flash-Next family (base, Coder, Swift 1.5) and Qwen3.6-35B-A3B. All runs used its low-RAM mode (experts mapped from the SSD) with thinking off, on the RTX 5060 Ti; "llama.cpp" is the same model file on our usual GPU + RAM split.

Model on Strata Decode (Strata) Decode (llama.cpp) Suite (11 categories) 24 bugs 80 bugs 80 bugs (llama.cpp) Real blockers (of 4)
Qwen3.8-Flash-Next IQ2_XS 67–79 tok/s ~19 tok/s 0.838 22/24 74/80 78/80 0 (one near miss)
Swift 1.5 Flash-Next IQ2_XS 64–71 tok/s ~19 tok/s 0.841 23/24 74/80 78/80 0
Swift 1.5 Flash-Next IQ3_XXS 58 tok/s ~19 tok/s 0.863 23/24 77/80 78/80 0
Flash-Next Coder IQ1_M 42–60 tok/s ~19–23 tok/s 0.860 18/24 72/80 77/80 0
Qwen3.6-35B-A3B UD-Q4_K_XL 71–89 tok/s ~22 tok/s (890M) 0.771 21/24 70/80 71/80 (890M) 0
For reference: Muse Glimmer 30B, medium (deep tier) ~52 tok/s 24/24 78/80 1
For reference: Gemma 4 26B (fast tier) ~200 tok/s 0.894 (8 cat.) 19/24 70/80

What Strata does well:

Why none was selected:

Where it could still pay off: an on-demand "fast review" mode for one person at the keyboard, a box with more RAM (its full-RAM mode), or a later release that closes the accuracy gap. Its install and launcher are kept (~/harness/tools/strata-trial.sh reruns every test above in one command).

Two lessons came with it. A prompt that invites "say none if none" made the models rubber-stamp: Glimmer answered "none" on all seven commits and the Coder build made 13 claims with none real. And most wrong claims were confident statements about Java and framework facts, so every local claim gets checked. The local deep tier reads long material and drafts first passes; the final call on a real review stays with Claude Code, which is exactly the split this setup is built on.

Full numbers for the deep tier

Latest model test — Swift 1.5 (2026-10-20, all builds measured): UkisAI's Swift 1.5 builds of the same models, tuned to think less at the same quality.

  • Credits: the Swift 1.5 reasoning fine-tunes of Qwen3.8 (27B and Flash-Next) and the GSQ-RCO GGUF files tested here are UkisAI's, downloaded from their Hugging Face repos ukisai/Swift-1.5-Qwen3.8-27B-GSQ-RCO-GGUF and ukisai/Swift-1.5-Qwen3.8-Flash-Next-GSQ-RCO-GGUF. Community quantizations of the same models (for example kunthawat's IQ3_XXS build of the 27B) were not part of these tests.

  • Swift 1.5 Qwen3.8-Flash-Next GSQ-RCO IQ2_XS (68 GB, experts in RAM, -ncmoe 36 on the 16 GB card): 24 of 24 seeded bugs with thinking off, in 5.8 minutes — the best score measured on this rig at the time (Muse Glimmer later found 80 of 80 on the bigger set; the current Coder deep tier: 22 of 24; the old GLM tier needed 26 minutes for 24). On the 80-item set it scored 0.975 (78 of 80), tying the best result on this rig (Coder deep tier: 0.963). A clean speed run (nothing else writing to the SSD) put it level with the current deep tier on output speed: 23.6 vs 26.1 tok/s (it reads long prompts slower: 161 vs 270 tok/s) — the earlier slow timings came from model downloads sharing the disk. More accurate at nearly the same speed: it's now an opt-in deep tier (llm deep start swift).

  • Swift 1.5 Flash-Next IQ3_XXS (76 GB, -ncmoe 40): also 24 of 24 and 78 of 80, but slower (9.7 and 34 minutes, ~4.5-4.8 tok/s) — the smaller IQ2_XS gets the same score faster, so it stays the pick among the Swift builds.
  • Swift 1.5 Flash-Next Q2_0 (66.5 GB, -ncmoe 32): 23 of 24 and 72 of 80 seeded bugs — clearly below IQ2_XS (24 and 78) at a similar size, so IQ2_XS remains the Swift pick.
  • Swift 1.5 Flash-Next IQ3_S (84 GB, the largest, -ncmoe 40): 24 of 24 and 78 of 80 — no better than IQ2_XS and slower (~6 tok/s). Verdict across all four Swift quants: IQ2_XS is the one to run (best score, smallest of the top scorers, as fast as the current deep tier).

Optimization tested: llama.cpp's new GPU cache for MoE experts kept in RAM (--moe-cache-mib, merged 2026-10-07; up to 2.2× on Flash-Next on desktop cards). On this rig the existing fixed layout stays fastest (Coder 28.7 tok/s, Swift 32.8); every cache setting was slower (15–28 tok/s). The likely reason is the eGPU link: the card hangs off OCuLink (PCIe x4), so each cache miss costs about 4× what it does in a desktop x16 slot. Worth re-testing with a card in an x16 slot.

New hardware (2026-10-18): a third GPU, the NPU and a second SSD.

Qwen3.8-Flash-Next (177B, about 6B active per token, Unsloth UD-Q2_K_XL, 79 GB) is the best big model so far, and the first that's quick enough for daytime use. It runs on the 5060 Ti with 40 expert layers in system RAM and the rest streaming from the fast SSD:

Qwen3.8-Flash-Next GLM-5.3-Flash (deep tier) DeepSeek-V4-Flash Gemma 4 (fast tier)
7-category suite 0.971 0.971 0.942 0.894
Seeded bugs (24) 24, in 9.5 min 24, in 26 min 21, in 12 min 19
Seeded bugs (80) 0.900 0.975 (low effort) 0.912 0.875
Script tasks (23) 22 — 17 19 (21 at max effort)
Decode 17–26 tok/s 3.6 tok/s 6–7 tok/s ~200 tok/s
  • Its MTP draft (a separate 4 GB Q8_0 file) adds only about 10%: 19.1 tok/s against 17.4, with 77% of drafted tokens accepted.
  • 64K context fits at the same 40 expert layers in RAM, with no quality loss: still 24 of 24 seeded bugs, and the long-prompt probe found all 12 functions in a 28K-token prompt (read at 150 tok/s, 3.4 min) and a 55K one.

Better builds of the same model: IST Austria's GSQ-RCO quants (the lab behind GPTQ). One keeps every expert at about 2.3 bits (IQ2_XS, 68 GB); the "Coder" build removes half the experts, chosen for code, tool use and vision, and stores the rest at about 3.5 bits (58 GB). Both load with -lm mmap -lzm on so a 29 GB n-gram shard stays on disk.

build size expert layers in RAM 7-category bugs (24) bugs (80) scripts (23) decode
GSQ-RCO Coder IQ1_M 58 GB 32 0.970 22, 3 min 0.963, 8 min 22 18–29 tok/s
GSQ-RCO IQ2_XS 68 GB 36 0.964 23 0.975, 10 min 21 14–21 tok/s
Unsloth UD-Q2_K_XL 79 GB 40 0.971 24, 9.5 min 0.900, 33 min 22 17–26 tok/s
  • The Coder build is the pick: smallest, fastest, and on the 80-item set within one bug of the best. IQ2_XS ties GLM-5.3-Flash at high effort (0.975) without thinking.
  • A 2,048-token thinking budget doesn't help the Coder build: 21 of 24 bugs in 25 min, against 22 in 3 min without thinking.

Nemotron-3.5-Super-VL 120B-A12B (UD-IQ2_XXS, 51 GB) loses everywhere. With 80 expert layers in RAM (fewer run out of VRAM) it decodes at 13–18 tok/s and scores 0.906 on the 7-category suite, 17 of 24 and 0.800 on the bug sets, 19 scripts and 5.5 tests. Its screenshot score (0.961) matches Gemma 4's, but takes 8 minutes against 84 s.

  • Fewer than 40 expert layers in RAM run out of VRAM.

DeepSeek-V4-Flash (284B, 13B active, Unsloth UD-IQ2_XXS, 91 GB) decodes about twice as fast as the GLM-5.3-Flash deep tier. On the 5060 Ti with experts in RAM and the rest streaming from the fast SSD: 4.98 tok/s at -ncmoe 40 -ub 2048 (prefill 27 tok/s), 5.75 tok/s with the default batch; GLM-5.3-Flash managed 2.91 in the same conditions. -ncmoe 36 and below run out of VRAM.

  • Its DSpark speculative decoder doesn't help here. The 11 GB draft model doesn't fit on the card next to the main model. On the CPU it's accepted about 65% of the time but slows decoding to 3.9–4.3 tok/s.
  • Quality: close to GLM-5.3-Flash, at about twice the speed, but Qwen3.8-Flash-Next (above) now beats it. 0.942 on the 7-category suite (GLM-5.3-Flash 0.971), 21 of 24 seeded bugs (GLM 24), 0.912 on the 80-item set (GLM 0.975 at high effort, Gemma 4 0.875), and 17 of 23 script tasks. It decoded at 6–7 tok/s during the suite, prefill about 65 tok/s. The 24 bugs took 12 minutes, against GLM-5.3-Flash's 26.

GLM-5.3-Flash (320B / 18B active), Unsloth UD-IQ2_XXS 102 GB, on llama.cpp CUDA with experts in RAM:

  • Best setting: -ncmoe 42 -ub 2048, giving 3.6 tok/s decode and 52 tok/s prompt (about 12× GLM-5.2).
  • Expert layers 36–40 on the GPU ran out of memory.
  • It always thinks; the template defaults to reasoning_effort=max. low is the cheapest option.
  • Best quality measured here: 0.971 on the full suite (effort=low, 3000-token budget) and 24/24 on bugauto, in about 26 min for those 24 items.
  • Now the deep tier: llm deep start swaps it onto the NVIDIA GPU in place of the fast model (loads in about 50 s), and requests run as background jobs whose answers land in a file.
  • First real job, open-ended "find bugs" on a 51-line file:
  • Template kwargs: a request's chat_template_kwargs replace the server's --chat-template-kwargs, so reasoning_effort=low has to be sent with every request.
  • Low temperature loops: at temperature 0.3 the 2-bit model looped, repeating the same reasoning lines for 6000 tokens (34 min, no answer).
  • Fix: the vendor sampling (temperature 1.0, top_p 0.95) plus llama.cpp's DRY anti-repetition sampler (dry_multiplier 0.8). It then finished on its own in 3.8K tokens (22 min).
  • Answer quality: 2 of 3 findings were real and subtle; 1 was wrong; line numbers were off. The 4-bit Qwen3.6 on the same prompt rambled without a conclusion.
  • Verdict: usable for an overnight second opinion, never interactively.
  • 102 GB of experts against 59 GB of RAM means a share of each token streams from the NVMe (about 1.9 GB/s of reads while decoding).
  • Decode drops to about 3 tok/s when anything else uses memory bandwidth.
  • Colibri's int4 Flash is 195 GB and would be disk-bound, so it wasn't tried.

Qwen3-Coder-Next 80B-A3B (UD-Q4_K_XL, -ncmoe 36 -ub 2048, GPU + RAM): 0.861 on the full suite. That's no better than Qwen3.6-35B, so it isn't worth the RAM.

The bigger 24-item seeded-bug set (bugauto) separates what the 5-item sets couldn't. Share of seeded bugs found:

model bugauto decode
GLM-5.3-Flash UD-IQ2_XXS (GPU + RAM) 1.000 3.6 tok/s
Qwen3.6-35B-A3B Q4_K_XL + MTP (AMD 890M, Vulkan) 0.917 22–30 tok/s
Qwen3.8-27B IQ4_XS + MTP (NVIDIA) 0.917 55 tok/s
Gemma-4-26B-A4B QAT Q4_K_XL + MTP (NVIDIA) 0.792 188 tok/s
Qwen3.6-35B-A3B IQ3_XXS + MTP (NVIDIA, the fast tier) 0.708 163–196 tok/s
LFM2.5-24B-A2B QAD-Q4_0 (NVIDIA) 0.042 192 tok/s
  • The 3-bit quant that makes the fast tier fit in 16 GB costs bug-finding. Reviews and bug hunts now go to the best tier (the 4-bit model on the iGPU), which moved to the MTP GGUF: about 22–24 tok/s in service, up from 19, at the same quality.
  • Qwen3.8-27B matches the iGPU model on bugs at about 2.5× its speed, but it can't be the main NVIDIA model.
  • Weights plus MTP draft come to 15.6 GB, leaving room for one 16K slot; 2 × 32K fails to load. The fast tier serves 2 × 32K, and real prompts reach 53K.
  • Without the draft it would decode at about 30 tok/s.
  • It stays an on-demand option for high-quality batches.
  • Better: the same 4-bit Qwen3.6 on the NVIDIA card with 20 expert layers in system RAM (-ncmoe 20 -ub 2048 -b 2048, 2 × 32K, MTP).
  • It keeps the iGPU tier's bug-finding (bugauto 0.917) at about 3× its speed.
  • Same 5.5K-token prompt, prompt / decode tok/s: 967 / 73 here, 1,892 / 142 on the fast tier, about 490 / 22 on the iGPU.
  • Every other category scores the same as the fast tier, so it's a switch rather than the default: llm profile review swaps the NVIDIA service to it (a systemd drop-in) and routes best there; llm profile fast reverts.
  • Smaller -ncmoe values (12, 16) run out of VRAM; 17 fits but isn't faster.

Qwen3.8-27B (dense, IQ4_XS + MTP draft) scored 0.942 on the 7-category suite, the best of the models that fit entirely on the GPU (only GLM-5.3-Flash, offloaded to RAM, scored higher). It's the only model to find all of the easy injected bugs (bugspot 1.00, against 0.60 for Qwen3.6). It runs at 62 tok/s and takes about 2.5× the wall time, which makes it a candidate for the best tier.

The final lineup#

Today's setup:

The two tiers miss different bugs. Gemma finds 70/80 and the iGPU Qwen 71/80; together they find 74/80.

Engines compared: llama.cpp (CUDA, Vulkan, ROCm), Ollama, Strata, Magnitude and more#

A model is the file; an engine is the program that runs it. The same file can run noticeably faster or slower depending on the engine, and occasionally score differently, so engines got the same treatment as models: same file, same prompts, speed and answers measured.

Head-to-head on one model (2026-10-21). Qwen3.5 9B (Unsloth UD-Q4_K_XL, the file Magnitude downloads), RTX 5060 Ti, a ~3.5K-token code-review prompt, 512 tokens out, temperature 0, thinking off, a fresh prompt every run so no engine could reuse a cached one; average of runs 2–4.

Engine Writing (tok/s) Prompt reading (tok/s) Time to first token VRAM in use
Magnitude 0.2.10 (its own auto-tuned kernels + speculative drafting) 84 2,440 1.4 s 10.6 GB
llama.cpp CUDA, with the model's built-in MTP drafter 70.5 2,780 1.3 s 6.3 GB
llama.cpp CUDA, plain 67 3,060 1.1 s 5.9 GB
Ollama 0.40.7, same file 67.6 3,040 1.1 s 6.0 GB
Ollama 0.40.7, its own library build (qwen3.5:9b) 68.5 3,020 1.2 s —

Everything else measured on this box:

Engine Where it ran Result Used for
llama.cpp, CUDA build RTX 5060 Ti Gemma 4 26B: 3,869 tok/s prompt, 140 tok/s writing (≈200 with MTP) Fast and deep tiers
llama.cpp, Vulkan build RTX 5060 Ti Same model: 3,238 / 123 tok/s; CUDA is 14–20% faster on NVIDIA —
llama.cpp, Vulkan build Radeon 890M, RX 7600 890M: Qwen3.6-35B ~23 tok/s; RX 7600: Qwen3.5 9B 834 / 39 tok/s, Ornith 9B ~95 with DFlash Best tier, third opinion
llama.cpp, ROCm build Radeon 890M 25.0 vs Vulkan's 23.4 tok/s writing, 471 vs 478 prompt; needs a GPU-ID override Vulkan kept (no override needed)
llama.cpp, ROCm build RX 7600 Doesn't run: Ubuntu's ROCm libraries have no kernels for this chip —
Strata RTX 5060 Ti 3–4× faster on big MoE models that spill into RAM (58–79 vs ~19 tok/s), 1–5 fewer of 80 seeded bugs On-demand option (see the deep tier)
FastFlowLM XDNA2 NPU Qwen3.6-35B ~18 tok/s, 20/23 scripts; a few watts NPU (in reserve)
Colibri NVIDIA + RAM + SSDs GLM-5.2 int4 streamed from both SSDs at ~0.4–0.6 tok/s Overnight experiments only
PrismML's llama.cpp fork RTX 5060 Ti Ternary-Bonsai-2-27B: ~48 tok/s, 64/80 seeded bugs —

What this shows:

The rest of the field, tested on every chip (2026-10-22). Each engine got the tier it could plausibly win, the same streaming prompt as above, and the full quality tests whenever it came close on speed.

Tier Best challenger Result vs. the current setup Verdict
Big MoE spilling into RAM (Qwen3.8-Flash-Next, NVIDIA + system RAM) ExLlamaV3 + TabbyAPI, 2.05 bpw, 400 experts per layer on the CPU 42 vs 26 tok/s writing, 579 vs 331 prompt; same quality (suite 0.884 vs 0.876, 24/24, 77 vs 78 of 80 seeded bugs) New winner for this mode; it needs the iGPU tier paused, because its experts live in ordinary RAM (~45 GB)
Fast tier (Gemma 4 26B + MTP, 2 × 32K) ik_llama.cpp; ExLlamaV3 3.5 bpw; vLLM (NVFP4) ik: 120 vs 133 tok/s with one slot only; ExLlamaV3: 87 tok/s (prompt reading +55%); vLLM: the weights alone fill the 16 GB card llama.cpp stays
Deep tier (Muse Glimmer 30B + DFlash, 64K) ik_llama.cpp; ExLlamaV3 + drafter ik ties without a drafter but can't fit DFlash; ExLlamaV3 35 tok/s but found 63 vs 78 of 80 bugs llama.cpp stays
iGPU and RX 7600 (Vulkan) ik_llama.cpp's Vulkan build Missing GPU kernels fall back to the CPU (under 1 tok/s) llama.cpp stays

Where local AI pays off#

Where the local tiers shine (measured overnight, 2026-10-19/20, inside real QA work): Claude teammates handed specific jobs to the local models and checked every answer against a known result.

Script generation: the full benchmark

Script generation, so analysis runs on the CPU instead of being read by an LLM.

  • The benchmark: 23 tasks, 12 core and 11 hard. The hard ones cover CSV quoting and UTF-8, paths with spaces, date math, joins, multi-line Java annotations, CLI arguments, nearest-rank percentiles, stable ties and a 400k-line stream.
  • How it runs: the model writes a Python or bash script, which runs in a bwrap sandbox (read-only root, no network, prlimit CPU and memory limits) against seeded fixtures. Its output must equal a reference answer.
  • Validation: a frontier model solving the tasks blind from the prompts scores 23/23, so the specs and references are consistent.
model core 12 hard 11 total time
Gemma 4 26B, thinking budget 2,048 12 9 21 ~5 min
Gemma 4 26B, no thinking 11 8 19 ~1 min
Qwen3.8-27B 10 9 19 2 min
Qwen3.6-35B-A3B IQ3 10 8 18 1 min
Qwen3-Coder-Next 80B-A3B (GPU + RAM) 10 8 18 12.5 min
Qwen3.6-35B-A3B Q4 (iGPU) 9 8 17 6 min
  • Effort levels on the 12 core tasks. A reasoning-token budget per request (thinking_budget_tokens; unbounded thinking was worse everywhere):
model no thinking budget 1,024 budget 2,048
Gemma 4 26B (NVIDIA) 11/12 (29 s) 10/12 (91 s) 12/12 (158 s)
Qwen3.6-35B-A3B Q4 (iGPU) 9/12 (152 s) 12/12 (752 s) 11/12 (1,050 s)

Hard set with a 2,048 budget: Gemma 9/11 (161 s), against 8/11 without thinking. - Which tasks fail:

task Gemma, budget 2,048 Gemma, no thinking Qwen3.8-27B Qwen3.6 Q4 + repair
multi-line, comment-aware Java annotations ✗ ✗ ✗ ✗
bash: line totals per directory, paths with spaces ✗ ✗ ✓ ✓
bash: 5xx count per IP in a time window ✓ ✗ ✗ ✗
everything else in the hard set ✓ ✓ ✓ ✓
  • Repair loop results (Qwen3.6 Q4, up to 2 rounds): core 9 → 9/12, hard 8 → 9/11.
  • Repair loop: feeding crashes, empty output or invalid JSON back to the model helps only with crashes. Wrong-but-running scripts need another signal.
  • That signal is agreement. When two different models independently wrote scripts with identical output, the answer was correct in 21 of 21 cases, and every disagreement marked a wrong script.
  • Failures cluster: every model failed comment-aware multi-line Java parsing, and bash scripts often broke on paths with spaces. So default to Python, and use a code map or code graph for code structure.
  • Prompt checklist: a "script-writing checklist" added to the prompt didn't help overall.
  • The local_script tool puts this together:
  • it writes the script, runs it on the real project tree mounted read-only, repairs crashes, and returns only the output;
  • optionally it has the second model write its own script and reports VERIFIED or DISAGREE;
  • it keeps useful scripts for reuse.
Code search, embeddings and code graphs

Embeddings (Qwen3-Embedding-0.6B Q8_0, prompt processing)#

Chip pp512 tok/s
NVIDIA 26,600
AMD 890M 4,900
CPU (12 threads) 1,185

The embedding model lives on the AMD iGPU, which keeps the NVIDIA card free for chat.

Code search: what works (known-answer queries on the real app)#

method hits, 10 queries hit@5, 30 queries MRR@5, 30 queries
grep (keywords from the question) 1/10 1/30 0.011
code map find (paths, symbols, local-LLM file summaries) 8/10 26/30 0.666
embeddings, Qwen3-Embedding-0.6B (semantic chunks) 8/10 28/30 0.840
embeddings, EmbeddingGemma 2 (740M, Q8) 28/30 0.797
hybrid: reciprocal-rank fusion of map and embeddings 9/10 29/30 0.856
  • Hybrid search is the default.
  • The 30-query run found that the tool fused only the top 5 semantic hits and counted each file once. It now fuses the top 10 of each list and counts every hit, which lifted MRR from 0.822 to 0.856.
  • EmbeddingGemma 2 tied on hits but ranked answers lower, so Qwen3-Embedding stays.

Code-graph MCP servers (same 3 questions on the real repo)#

codebase-memory-mcp 0.11.0 (46.6K stars, 0 advisories) Gortex 0.64.8 (1.9K stars, 5 advisories, all patched)
index 6 s, no daemon, 59 MB on disk 22 s, daemon using 89 MB RAM, 43K nodes / 167K edges
callers of a component correct (matches grep ground truth) empty when queried by name; needs a fully qualified ID
impact of a shared component 15 callers in 14 files (matches grep) empty when queried by name

codebase-memory-mcp was kept. Gortex's daemon was stopped.

Claude-side agents (for scale)
  • Per-agent cost: a harness-guided UI audit agent costs about 50–65K Claude tokens, regardless of scope.
  • Cost per finding: about 10–12K tokens per verified finding at best.
  • Model choice: Haiku used more tokens than Sonnet (69.6K over 17 calls against 52.6K over 10), but at a fraction of the price. That makes Haiku the cheaper choice when the harness does the measuring.
  • What helped most: going map-first (code map and graph before reading files). It cut screenshots to 0 and source reads to about 200 lines.
The first QA round with this setup

First real QA round with this setup (2026-10-19): two Claude teammates ran discovery on a real production web app (its data pipeline and generated reports checked against the data) with the local tools available, and found 14 verified problems (6 P2).

  • None of the 14 came from a local model. Local first-pass hunts over long service files produced plausible but wrong claims (an authorization hole the resource layer already blocks, a double count a query already prevents); the teammates refuted each one.
  • The one useful local result was a cross-check: a generated script with a second, independent script recomputed a form's totals and confirmed the app's arithmetic (the two scripts disagreed, and the one that matched the API was right).
  • Caveat: the teammates' tool server predated the three-model mode, so they ran the two-model mode. The next round measures the three-model mode and the deep tier's commit pre-review against the Claude reviewer.

Does a hybrid AI harness really save Claude tokens? (measured)#

This setup is a hybrid AI harness: Claude Code orchestrates (with Claude itself running in the cloud), local models on the home PC's chips take the reading and drafting, and deterministic scripts on the CPU do the counting and checking. Handing work off isn't free, though. Claude writes every request and reads every answer back. So does the prep and relay eat the savings? We measured four days of real work on a real software project (2026-10-18 to 22): 221 Claude Code transcripts, 17,105 Claude tool calls and 423 local-model calls.

The answer: a modest, real saving, and it depends on the job. Tokens are Claude's new-context tokens (≈ characters / 4; images by Anthropic's vision formula). The three columns differ in what Claude would have done without the hand-off.

Over 4 days Generous (Claude would have read everything handed over) Realistic (minus what Claude read anyway) Strict (any touch of the same files = no saving)
Local model calls (423, 62 failed) +6.8 M +1.10 M −0.09 M
Bounded command-line tools +4 M +0.2 M +0.2 M
Fixed overhead (instructions, playbook, tool schemas) −0.48 M −0.48 M −0.48 M
Net ≈ +10 M ≈ +0.8 M (≈1.3% of ~60 M new-context tokens) ≈ −0.4 M

A local result stays in Claude's context for a median of 33 more turns, which multiplies both the saving and the cost.

Where it pays, and where it doesn't (realistic accounting, per job type):

Job Calls Net for Claude Why
Screenshot read as text 70 +121k ~192 tokens per image instead of ~1,106 if Claude looked at it; 38 s median
Summarize / extract from big files 42 +145k (strict: −117k) big input in, short answer out; but Claude opened the same file anyway 83% of the time
Scripted counting (a local model writes the script, the CPU runs it) 63 +103k the data never enters Claude's context
Semantic code search 45 +9k about break-even with a careful grep
Bug hunt / review on files 134 +689k (strict: −181k) median answer 1,413 tokens (p90 4,883), 20% cut off; Claude re-read the files after 54% of calls; ~1 claim in 14 held up
Screenshot critique ("what's wrong here?") 16 +15k (strict: −9k) 457 tokens per image, 7.3 min median, ~1 real finding in 60 claims

The hidden costs:

Problems → solutions (now applied):

Problem Fix
Long, mostly wrong bug-hunt answers Capped, structured claims (file:line + the quoted line + one sentence); drop any claim whose quoted line isn't in the file; one model by default; treat the answer as a checklist for files Claude reads anyway
Hangs and timeouts A server-side deadline (~5 min) that returns a partial answer, a health check before fanning out, fail fast
Fixed overhead eats half the gain Shorter always-loaded instructions, a 5-line digest instead of the playbook, tool schemas only where they're used
Screenshot critique is costly and unreliable Transcribe screens as text; judge layout with deterministic checks
Script cross-checks disagree a third of the time Return only the agreed result, or a short field-by-field diff
Grouped search isn't a token saver Keep it for readability and safety; the real wins are outlines and digests

Before → after the fixes (a fixed benchmark on the same machine, old version vs new):

Measure Before After
Bug-hunt answer Claude reads, per call ~3,200 tokens ~290 tokens (−91%)
Claims to read across 6 hunts 95 25
Seeded bug named 6/6 6/6
… at the exact line 4/6 6/6
Hunt wall time (median) 109 s 64 s
Best tier hitting its answer cap 3/6 0/6
Script cross-check correct 1/2 2/2
Text read from a contact sheet 5.5% (fast tier, looped) / 78% (best tier) 92.5%
Calls stuck for 30 minutes 9 overnight none: every call returns by its deadline (≤5 min)
Tool schemas loaded into every context 10.0K characters 5.8K characters

The lesson: send local models the reading and counting, and keep the judging with Claude. Claude Code stays the orchestrator and makes every final call.

Is a 16 GB GPU worth it, or is the CPU enough?#

Which chip carried the saving (realistic accounting): the Radeon 890M iGPU served 57% of the calls and 54% of the saving, including most of the winning jobs: 60 of 70 screenshot readings, 30 of 42 summaries and 38 of 63 scripted counts. The RTX 5060 Ti (fast and deep) carried ~40%, but 85% of that came from bug hunts. Under strict accounting the 5060 Ti's fast tier is the only chip clearly in the black (+112k), because its answers are short and arrive fast. So the wins don't require the card. What the card buys is speed.

Speed: what an agent waits for (same jobs, from the local server's log):

Job (typical size) RTX 5060 Ti Radeon 890M iGPU CPU only (estimate)
Write speed, same 3.5–5.5K prompt 142–148 tok/s ~22 tok/s ~11 tok/s
Prompt reading 1,900–2,150 tok/s 357–490 tok/s ~140 tok/s
Scripted counting (1.6K in, 3.1K out) 18.5 s 144 s ~5 min
Screenshot read as text 6 s 18 s ~40 s
Summary / extraction (2–4K in) 3 s 39 s ~40 s
Bug-hunt pass (9.7K in, 1.6K out) 18 s 220 s ~3.5 min

Running cost:

Measured
RTX 5060 Ti idle, model loaded 7.9 W
Answering one request (3.8K in, 400 out) 110–173 W, mean ~130 W, ≈0.26 Wh per request
Card energy, this window's use (~0.6 h/day busy) 0.31 kWh/day ≈ US$0.08/day
Card energy, heavy use (8 h/day of batch jobs) 1.43 kWh/day ≈ US$0.37/day
CPU-only instead no card, but ~10× longer per job and it competes with the host for memory bandwidth: a 5-minute script job ≈ 2.5 Wh vs ≈ 0.7 Wh on the card (CPU power assumed)

Electricity at a Philippine residential rate of ₱15.06/kWh (October 2026), ₱58 per US$, plus 15% for the eGPU dock and PSU (assumptions).

Price and payback. The card costs US$770–810 street in October 2026 (it launched at $429 and rose with the memory shortage). Payback depends on how you pay for Claude:

Scenario (realistic) Saving per day Card payback (energy deducted)
Today, all local chips $1.10–2.50 320–770 days
After the fixes (estimate) $1.55–3.60 220–520 days
Only the 5060 Ti's share $0.35–0.80 3–8 years
Scripts on the CPU, no model $3.70–35 no hardware needed

The third path: invest in scripts and let the CPU run them. Over the same four days Claude wrote 246k tokens of script code (218 reusable scripts plus 6 bounded command-line tools) and re-ran those scripts 1,318 times. Reading a run's result costs Claude a median of 230 tokens, against ~305 for a hand-run probe. A script pays back after a median of 2.3 runs (up to 8), 54 of 94 had already paid back, and the realised net is +2.8 M to +11 M tokens. Honest caveat: without scripts, agents would check less rather than spend those tokens; what scripts really buy is near-free re-checking (~200 tokens for a full regression run). Scripts can't read a screenshot or summarise free text, and a model can't beat a script at counting, invariants or regressions.

The verdict, as a ladder:

  1. Scripts on the CPU first. Cheap and exact, no GPU needed, they pay back after 2–8 runs, and they were the biggest saving in the data. A local model is good at drafting them.
  2. A local model for what scripts can't do: reading screenshots as text (~190 vs ~1,100 Claude tokens per image), summarising and extracting from big inputs, drafting scripts and tests. Keep the judging with Claude.
  3. A 16 GB GPU when that model work is daily and someone is waiting on it. It runs 26–35B mixture-of-experts models entirely in VRAM at 140–200 tok/s, reads screenshots, and turns a 2–7 minute iGPU wait into 5–20 s. - Worth it for heavy daily agent use, screenshot- and reading-heavy work, privacy or offline use, and overnight batch jobs. - Not worth it for light use, for hoping it will find your bugs, or for API money alone: at today's price the card's own share pays back in years, and the whole local setup in about 7 months to 2 years. - 16 GB can't hold dense 27B+ models at high quality or 100B+ models; those need RAM offload (ExLlamaV3 42 tok/s, Strata 58–79 tok/s) or don't fit.
  4. CPU-only models as the fallback. No purchase, but ~11 tok/s and minutes per job. Fine for small overnight jobs, too slow for an agent waiting in the loop. A recent iGPU with shared RAM (the 890M here) sits in between, and in this window it served most of the winning calls.
Sources and method (checked 2026-10-22)
  • Data: 221 Claude Code transcripts (3 main sessions, 218 subagents) and the local server's call log, 2026-10-18 to 22. Read-only replays; tokens ≈ characters / 4. Power was sampled with nvidia-smi on 2026-10-22, and the CPU bench was a CPU-only llama.cpp run taken while the other tiers were serving.
  • Anthropic pricing (Claude Opus 5.5: $4 input, $5 5-minute cache write, $0.20 cache read, $20 output per MTok), read 2026-10-22.
  • Electricity: Meralco October 2026 residential rate ₱15.0615/kWh (Daily Tribune, 2026-10-13, Philstar, 2026-10-14).
  • RTX 5060 Ti 16 GB price: US street median $804.99, Aug–Sep 2026 (TweakTown); lowest $766 on 2026-10-22 (gpuprix); launch MSRP $429 (Gadget Pilipinas, 2025-04).

Finding the sweet spot: quality vs savings#

The sweet spot is the setting where local work is good enough to trust and costs Claude fewer tokens than doing it itself. We found it with three levers, each measured rather than guessed.

The process: three levers.

  1. Which model on each chip. Every candidate ran the same tests: the suite score, the 24- and 80-item seeded-bug sets, unit tests, scripts, screenshots, and, for the deep tier, real commits with known blockers. Speed was measured on this rig too. Each chip gets the best quality that fits its job: the fast tier needs speed (Gemma 4, ~200 tok/s, 70/80 bugs), the deep tier needs accuracy (Muse Glimmer, ~52 tok/s, 78/80 bugs and the only real blocker caught).
  2. How much to think, and how many models to ask. - A capped thinking budget beats both extremes. On the 80 seeded bugs, Gemma 4 scores 0.875 with thinking off, 0.912 at 1,024 tokens and 0.963 at 2,048, but 0.05 with unbounded thinking. Qwen3.6 drops from 0.887 to 0.800 unbounded and takes 2.5 h instead of 7 min. - Two tiers in parallel for bug hunts: Gemma finds 70/80 and Qwen3.6 71/80, but together they find 74/80. - The slow, accurate deep tier only for background jobs, where nobody is waiting. - Speed tricks only when the answers stay the same: the DFlash drafter (2.5× faster, same score) and ExLlamaV3 for big models in RAM (1.6× faster, 77 vs 78 of 80) passed; Strata (3–4× faster, 1–5 fewer of 80 bugs) didn't.
  3. Which jobs to hand off at all, and how. The token economics above decide this. The wins are big-in, small-out jobs (screenshots read as text, scripted counting, outlines and digests); the losses are first-pass bug hunts and screenshot critique, plus the fixed overhead every agent pays. The efficiency fixes then trim the losses: capped structured answers, a quote-the-line filter and hard timeouts. On a fixed benchmark they cut the bug-hunt answer Claude reads from ~3,200 to ~290 tokens per call, still named the seeded bug 6 of 6 times (now 6 of 6 at the exact line, up from 4), and no call hangs past its deadline.

The result: today's sweet spot.

Job Where it runs Quality Claude-token cost
Counting, invariants, regressions Scripts on the CPU (a local model drafts them) exact; double-checked scripts must agree ~230 tokens to read a run; pays back after 2–8 runs
Reading screenshots Local vision, text mode ~100 labels, dates and numbers read exactly, nothing invented ~192 tokens per image instead of ~1,106
Reading and summarising big inputs and logs Local fast tier (Gemma 4) named the root error in 3 of 3 logs, in 1–5 s a short answer back; pays when Claude wouldn't open the file anyway
Code structure, command output Bounded tools, no model kept 100% of what mattered in replays (96.7% for JSON) up to ~10.9k tokens saved per outline
First-pass bug hunts Optional: two tiers, capped thinking, claims must quote the line; never trusted on their own 74/80 seeded bugs together, but ~1 real claim in 14 ~290 tokens per call in the compact format (was ~3,200); Claude still re-reads the code
Overnight deep review Deep tier (Muse Glimmer), every claim verified by Claude 78/80 seeded bugs; the only local model that caught a real blocker runs in the background; Claude reads only what survives verification
Judging, reviews, fixes Claude the final call on every claim where Claude's tokens are worth spending

Rule of thumb: measure quality and Claude-token cost on your own work before switching anything. The sweet spot moves: the lineup changed at least three times in these four days (the deep tier twice, and the RX 7600 gained its drafter), and every change came from a measurement.

What's next#

Experiment queue and history
  • From an outside recommendation list (2026-10-18), status:
  • Done: Vulkan vs CUDA on the RTX 5060 Ti (CUDA wins), Qwen3-Coder-30B, Llama 3.1 8B, Mistral Nemo 12B, Ling 3.0 Tiny, Qwen3.5 9B without thinking (see finding 3).
  • Also done: the DeepSeek-R1 distills, Qwen3.5 9B with a thinking budget, the NPU suite, the deep tier from each SSD, DeepSeek-V4-Flash speed and DSpark, Colibri GLM-5.2 cold runs.
  • Also done: DeepSeek-V4-Flash quality suite, the NPU re-check, Ornith-1.5 9B and 35B.
  • Also done: Qwen3.8-Flash-Next in three builds (speed, MTP, full suite, 64K context), Qwen3.8-27B GSQ-RCO in the fast tier's shape, Nemotron-3.5-Super-VL, Colibri GLM-5.2 on Vulkan and warm, the smaller NPU models, long-prompt probe, test writing at 4,096 tokens.
  • Also done: the Coder build with thinking (same 80-item score, ~10x slower), at 64K context (fits, 12/12 at 55K), and as the deep tier on real jobs: commit reviews in under 70 s with nothing invented, but open-ended single-file bug hunts claimed false DOM facts in 5 of 6 runs.
  • Done 2026-10-19: the Coder build is the deep tier (GLM-5.3-Flash deleted); the RX 7600 serves Ornith-1.5-9B as a third opinion; first QA round run with the local tiers (see Today's setup).
  • Next: measure the three-model mode and the deep commit pre-review against the Claude reviewer in the second QA round; try Qwen3.8-27B as a switchable review mode.
  • Original list:
  • Small dense models for speed:
    • Qwen3.5 9B (Q4_K_M and Q8_0)
    • DeepSeek-R1-Distill-Qwen 7B/8B
    • Llama 3.1 8B (Q8_0)
    • Mistral Nemo 12B
  • Ling 3.0 Tiny (7.9B MoE, claimed 120+ tok/s).
  • Qwen3-Coder-30B (Unsloth UD-Q3_K_XL, GPU only).
  • Each one runs through the same suites (bug-finding, script generation, test writing, vision where relevant) against the current fast tier, Gemma 4 26B.
  • Image generation (FLUX.1 / SDXL) is out of scope for this harness.

  • Deep tier: solved by switching models: the pruned Qwen3.8-Flash-Next Coder build (58 GB) fits with room for 64K context, where no GLM-5.3-Flash quant fit in RAM.

  • Whole-file rewrite task: decide whether n-gram speculation is worth it (low priority: delegated work is mostly summaries and extraction).
  • Nemotron 3.5 Super VL (120B / 12B active): tested; loses to Qwen3.8-Flash-Next on code and to Gemma 4 on screenshots (finding 3).
  • Done 2026-10-21: Ornith-1.5-122B, Qwen3.8-27B IQ4_XS partial offload, the Strata engine (all five models it supports), and the Ornith-1.5-9B DFlash drafter (adopted on the RX 7600). DeepSeek-V4.1-Flash-1017 (763B; smallest GGUF 233 GB) is out of reach for 59 GB of RAM.
  • Hardware levers measured: 128 GB RAM would hold GLM-5.3-Flash's experts entirely. A second NVMe was added on 2026-10-18: it speeds up expert streaming by about 20% (finding 3).

Recreate this setup#

These steps rebuild the local stack on any Ubuntu 24.04 or 26.04 machine with an NVIDIA card (16 GB) and/or an AMD iGPU.

1. System packages (needs sudo; run them in your own terminal, not through an AI agent)#

# NVIDIA driver (open kernel modules). Install the driver package, not just -utils, so the kernel modules match.
sudo apt install nvidia-driver-595-server-open nvidia-utils-595-server
# eGPU over OCuLink/Thunderbolt: power the dock BEFORE booting. OCuLink is not hot-pluggable.

# Vulkan headers + shader compiler (only needed to build Colibri's Vulkan backend)
sudo apt install libvulkan-dev glslc mesa-vulkan-drivers

# CUDA toolkit (only needed to build Colibri's CUDA backend; llama.cpp ships prebuilt CUDA binaries).
# NVIDIA's ubuntu2404 repo also works on 26.04.
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb && sudo apt update && sudo apt install cuda-toolkit-13-0

# Let user services start at boot without a login
sudo loginctl enable-linger "$USER"

2. llama.cpp prebuilt binaries (Vulkan for AMD, CUDA for NVIDIA)#

B=b11642; R=https://github.com/ggml-org/llama.cpp/releases/download/$B
mkdir -p $LLM_HOME/bin/vulkan $LLM_HOME/bin/cuda $LLM_HOME/models
curl -L $R/llama-$B-bin-ubuntu-vulkan-x64.tar.gz | tar xz -C $LLM_HOME/bin/vulkan --strip-components=1
curl -L $R/llama-$B-bin-ubuntu-cuda-12.8-x64.tar.gz | tar xz -C $LLM_HOME/bin/cuda --strip-components=1
# The CUDA build needs the CUDA runtime next to it. Extract fully, THEN copy (copying mid-extract caused a bus error).
curl -L $R/cudart-llama-$B-bin-ubuntu-cuda-12.8-x64.tar.gz -o /tmp/cudart.tgz && mkdir -p /tmp/cudart \
  && tar xzf /tmp/cudart.tgz -C /tmp/cudart && cp /tmp/cudart/*/lib*.so* $LLM_HOME/bin/cuda/

Notes:

3. Models (Hugging Face, resumable)#

get() { mkdir -p "$LLM_HOME/models/$1"; curl -fL -C - -o "$LLM_HOME/models/$1/$(basename "$3")" "https://huggingface.co/$2/resolve/main/$3"; }
get qwen36-mtp unsloth/Qwen3.6-35B-A3B-MTP-GGUF Qwen3.6-35B-A3B-UD-IQ3_XXS.gguf   # NVIDIA fast tier (14.1 GB)
get qwen36-mtp unsloth/Qwen3.6-35B-A3B-MTP-GGUF Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf   # AMD best tier (22.9 GB)
get qwen36     unsloth/Qwen3.6-35B-A3B-GGUF     mmproj-F16.gguf                    # vision encoder
get embed      Qwen/Qwen3-Embedding-0.6B-GGUF   Qwen3-Embedding-0.6B-Q8_0.gguf
# optional
get qwen38-27b unsloth/Qwen3.8-27B-GGUF Qwen3.8-27B-UD-IQ4_XS.gguf
get qwen38-27b unsloth/Qwen3.8-27B-GGUF MTP/mtp-Qwen3.8-27B-Q4_0.gguf
for i in 1 2 3 4; do get glm53flash unsloth/GLM-5.3-Flash-GGUF UD-IQ2_XXS/GLM-5.3-Flash-UD-IQ2_XXS-0000$i-of-00004.gguf & done; wait

4. Servers (systemd user units)#

The units below are the originals that started this setup; today's tiers are in "The final lineup" above (fast tier Gemma 4, deep tier Muse Glimmer 30B). Swap the model paths and flags from the results to recreate the current lineup.

Set Environment=LLM_HOME= to your directory in each unit; systemd expands ${LLM_HOME} in ExecStart only from Environment= lines.

Fast tier, NVIDIA 16 GB: Qwen3.6 with MTP speculative decoding (~196 tok/s), with vision.

# ~/.config/systemd/user/llm-nv.service
[Service]
Environment=LLM_HOME=/opt/llm
Environment=LD_LIBRARY_PATH=/opt/llm/bin/cuda
ExecStart=${LLM_HOME}/bin/cuda/llama-server -m ${LLM_HOME}/models/qwen36-mtp/Qwen3.6-35B-A3B-UD-IQ3_XXS.gguf \
  --mmproj ${LLM_HOME}/models/qwen36/mmproj-F16.gguf --no-mmproj-offload \
  --host 127.0.0.1 --port 8093 -ngl 99 -fa on -c 65536 -np 2 -ctk q8_0 -ctv q8_0 \
  --spec-type draft-mtp --image-max-tokens 2048 --sleep-idle-seconds 1800
Restart=on-failure
[Install]
WantedBy=default.target

Notes on the fast tier:

Best tier, AMD iGPU (shares system RAM): same model family at Q4.

[Service]
Environment=LLM_HOME=/opt/llm
Environment=VK_DRIVER_FILES=/usr/share/vulkan/icd.d/radeon_icd.json
ExecStart=${LLM_HOME}/bin/vulkan/llama-server -m ${LLM_HOME}/models/qwen36-mtp/Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf \
  --mmproj ${LLM_HOME}/models/qwen36/mmproj-F16.gguf --host 127.0.0.1 --port 8091 \
  -ngl 99 -fa on -c 131072 -np 2 -ctk q8_0 -ctv q8_0 --image-max-tokens 2048 --sleep-idle-seconds 1800

VK_DRIVER_FILES pins Vulkan to the Radeon when an NVIDIA card is also present. On Ubuntu 26.04 the file is radeon_icd.json.

Embeddings on the AMD iGPU:

llama-server -m Qwen3-Embedding-0.6B-Q8_0.gguf --port 8092 -ngl 99 --embedding --pooling last \
  -c 16384 -b 4096 -ub 4096 -np 4 --sleep-idle-seconds 1800

Big MoE with experts in RAM: GLM-5.3-Flash on NVIDIA plus RAM, batch jobs only (3.6 tok/s).

llama-server -m GLM-5.3-Flash-UD-IQ2_XXS-00001-of-00004.gguf -ngl 99 -ncmoe 42 -ub 2048 -b 2048 \
  -fa on -c 16384 -np 1 -ctk q8_0 -ctv q8_0 --port 8000
# send "chat_template_kwargs": {"reasoning_effort": "low"}: GLM-5.3 models always think, and the default is max

Activate the units:

systemctl --user daemon-reload && systemctl --user enable --now llm-nv llm-amd llm-embed

5. Find your own offload point for a big MoE#

Sweep --n-cpu-moe, then keep the lowest value that loads:

for n in 99 46 44 42 40; do
  LD_LIBRARY_PATH=$LLM_HOME/bin/cuda $LLM_HOME/bin/cuda/llama-bench -m MODEL.gguf -ngl 99 -ncmoe $n \
    -fa 1 -ctk q8_0 -ctv q8_0 -ub 2048 -b 2048 -p 4096 -n 32 -r 1 -o md || echo "ncmoe=$n OOM"
done

Bigger -ub and -b values (2048) raised prompt speed 2.7× when the experts live in RAM.

6. Colibri (only if you have lots of RAM and fast or multiple NVMe drives)#

git clone --depth 1 --branch v2.0.0 https://github.com/JustVugg/colibri && cd colibri/c
make -j16 colibri ARCH=native && cp colibri colibri-cpu                                   # CPU
make clean && make -j16 colibri CUDA=1 CUDA_ARCH=sm_120 CUDA_HOME=/usr/local/cuda ARCH=native && cp colibri colibri-cuda   # CUDA 13 toolkit from step 1
make clean && make -j16 colibri VK=1 ARCH=native && cp colibri colibri-vk               # Vulkan (needs libvulkan-dev + glslc)
ln -sf colibri-cuda colibri                                                              # the variant `coli` will run
cd .. && ./start-here.sh --model glm-5.2 --yes --backend cpu --dir <models dir>   # 429 GB download
# start-here.sh auto-starts a server on :8000 when the download finishes; stop it before running your own service

With 60 GB RAM and one NVMe, expect about 0.3 tok/s for GLM-5.2, and a prefill too slow for prompts over about 2K tokens.

7. Wire it into Claude Code (or any agent)#

Register it with claude mcp add -s user local-llm -- python3 <server.py>. - Smoke-test before reconnecting: send initialize and tools/list over stdio first. A syntax error makes /mcp reconnect fail with only "connection closed". - Delegation rules in the global CLAUDE.md: send bulk, low-stakes, verifiable work to local models (extraction, first-pass diff review, drafts, screenshot triage). Keep decisions, subtle bugs and security with Claude, and verify what local models claim.

8. Measure speed AND quality before switching models#

Build a small eval from your own codebase, with answers that can be scored automatically:

task ground truth score
list a controller's HTTP endpoints parsed from the annotations F1
list the API client calls in a UI file regex over the source F1
strict JSON summary of a file the file's exported symbols valid JSON + F1
write small functions hidden test cases run with bun pass rate per case
find one injected operator bug (>=→>, ??→\|\|, .some→.every) the mutated line line ±1

Notes:

Lab notebook: every result and log#

Everything measured, in full. Each section opens on click.

The full results table

The evals use the app's real code, pinned at one commit, and are scored automatically (see "How models are compared" below). "—" means not run.

Model (role) Runs on Full suite Bugs found (80) Scripts (23) Unit tests (9) Vision (20 pages) Decode tok/s
In use now
Gemma 4 26B-A4B QAT + MTP (fast tier) NVIDIA 0.894 0.875 (0.963 with a 2K thinking budget) 19 (21 at max effort) 7 0.965 ~200
Qwen3.6-35B-A3B Q4_K_XL + MTP (best tier) iGPU 0.878* 0.887 (0.963 with a 2K budget) 17–18 3 0.968 ~22–24
Qwen3.8-Flash-Next GSQ-RCO-Coder IQ1_M (deep tier since 2026-10-19) NVIDIA + RAM 0.970* 0.963 (24-item set: 0.917) 22 1 — ~18–29
Ornith-1.5-9B Q4_K_M, thinking budget 1,024 (third opinion) RX 7600 0.810† 0.825 (24-item set: 0.750) 16 6 — ~32
Top candidates (best bug scores first)
Muse Glimmer 30B UD-IQ3_XXS (Meta, dense), low reasoning strength NVIDIA only (32K) 0.925 (thinks always) 1.000 (24-item set: 0.958) 21 6 0.931 ~30 (~57 with DFlash)
Swift 1.5 Qwen3.8-27B IQ3_XXS + MTP, low thinking effort NVIDIA only (2 × 32K) 0.840 (no thinking) 0.975 (24-item set: 1.000) 22 2.5 0.965 ~60–64
Swift 1.5 Qwen3.8-27B IQ3_XXS + MTP, kunthawat's community build, low thinking effort NVIDIA only (2 × 32K, or 1 × 100K) 0.858 (no thinking) 0.975 (24-item set: 0.958) 21 (22 with thinking off) 2 0.964 ~60–66
Qwen3.8-27B GSQ-RCO IQ3_XXS + MTP (base), low thinking effort NVIDIA only (2 × 32K) — 0.975 (24-item set: 0.958) 23 — — ~63
Swift 1.5 Qwen3.8-Flash-Next GSQ-RCO IQ2_XS (opt-in deep tier) NVIDIA + RAM — 0.975 (24-item set: 1.000) — — — ~24
Qwen3.8-Flash-Next GSQ-RCO IQ2_XS NVIDIA + RAM 0.964* 0.975 (24-item set: 0.958) 21 1 — ~14–21
Swift 1.5 Qwen3.8-Flash-Next IQ3_XXS / IQ3_S NVIDIA + RAM — 0.975 (24-item set: 1.000) — — — ~4.5–6
Qwen3.8-27B GSQ-RCO IQ3_S + MTP (review candidate) NVIDIA (2 × 32K) 0.837†§ 0.925 (24-item set: 0.875) 20 2 0.965 ~56–64
Swift 1.5 Qwen3.8-Flash-Next Q2_0 NVIDIA + RAM — 0.900 (24-item set: 0.958) — — — ~9
Qwen3.8-Flash-Next UD-Q2_K_XL NVIDIA + RAM 0.971* 0.900 (24-item set: 1.000) 22 5 — ~17–26
Qwen3.8-27B IQ4_XS + MTP NVIDIA (16K context only) 0.942* — (24-item set: 0.917) 19 — — ~55
Other models tested on the GPUs
gpt-oss-20b MXFP4, low effort NVIDIA (2 × 32K) 0.884 0.812 19 7 — (no vision) ~128 (~138 with EAGLE3)
Devstral Small 2 24B IQ4_XS (Mistral, dense coder) NVIDIA (32K) 0.780 0.650 17 5 — ~31
DeepSeek-V4-Flash UD-IQ2_XXS (deep-tier candidate) NVIDIA + RAM 0.942* 0.912 (24-item set: 0.875) 17 1 — ~6–7
Ornith-1.5-35B-A3B IQ3_XXS, thinking budget 2,048 NVIDIA — 0.887 (24-item set: 0.792) 19 6 — ~113
Nemotron-3.5-Super-VL 120B-A12B UD-IQ2_XXS NVIDIA + RAM 0.906* 0.800 (24-item set: 0.708) 19 5.5 0.961 ~13–18
Ternary-Bonsai-2-27B PQ2_0 NVIDIA (PrismML fork) 0.877 0.800 — — — ~48
Ornith-1.5-35B-A3B Q4_K_M, no thinking iGPU 0.776† 0.762 19 2 — ~12
Qwen3-Coder-30B-A3B UD-Q3_K_XL NVIDIA 0.838 0.738 17 3 — ~106
Ornith-1.5-35B-A3B IQ3_XXS, no thinking NVIDIA 0.723† 0.688 16 2 — ~112
Nemotron-3.5-Bolt 74B-A9B iGPU — 0.688 — — — ~11
Qwen3-Coder-Next 80B-A3B NVIDIA + RAM 0.861* — 18 — — —
LFM2.5-24B-A2B NVIDIA 0.591 — (24-item set: 0.04) — — — ~192
LFM2.5-1.2B-Instruct Q4_K_M NVIDIA 0.198 0.062 (24-item set: 0.083) 0 0 — ~448
LFM2.5-VL-1.6B Q8_0 NVIDIA — — — — 0.436 —
MiniCPM-V 4.7 35B-A3B / 1B iGPU / CPU only — — — — 0.939 / 0.838 —
Small models on the RX 7600
Qwen3.5-9B Q4_K_M, thinking budget 1,024 RX 7600 0.773† — (24-item set: 0.583) 17 5 — ~37
Qwen3.5-9B Q4_K_M, no thinking RX 7600 0.743† — (24-item set: 0.458) 13 3 — ~38
Ornith-1.5-9B Q4_K_M, no thinking RX 7600 0.698† — (24-item set: 0.583) 13 2 — ~37
Ling-3.0-tiny Q4_K_M RX 7600 0.604† — (24-item set: 0.125) 13 0 — ~85
Llama-3.1-8B Q4_K_M RX 7600 0.541† — (24-item set: 0.167) 5 2.5 — ~45
Mistral-Nemo-12B Q4_K_M RX 7600 0.524† — (24-item set: 0.125) 8 3 — ~30
DeepSeek-R1-Distill-Llama-8B, budget 2,048 RX 7600 0.461† — (24-item set: 0.167) 3 4 — ~43
DeepSeek-R1-Distill-Qwen-7B, budget 2,048 RX 7600 0.365† — (24-item set: 0.125) 3 1 — ~47
On the NPU (FastFlowLM)
Qwen3.6-35B-A3B (FastFlowLM) NPU 0.777† — (24-item set: 0.625) 20 2 — ~18
Gemma 4 E4B (FastFlowLM) NPU 0.690† — (24-item set: 0.167) 15 6 — ~12
Qwen3 4B Instruct (FastFlowLM) NPU 0.594† — (24-item set: 0.333) 10 2 — ~17
Gemma 4 12B (FastFlowLM) NPU 0.592† — (24-item set: 0.750) 16‡ 5‡ — ~7
Qwen3.5 9B (FastFlowLM) NPU 0.555† — (24-item set: 0.458) 2‡ 0‡ — ~7–9
Llama 3.1 8B (FastFlowLM) NPU 0.535† — (24-item set: 0.208) 4 3 — ~12
gpt-oss 20B (FastFlowLM) NPU 0.407† — (24-item set: 0.167) 9 1 — ~20
Phi-4-mini (FastFlowLM) NPU 0.352† — (24-item set: 0.125) 2 0 — ~19
Retired
Qwen3.6-35B-A3B IQ3_XXS + MTP (old fast tier) NVIDIA ~0.863 0.662 18 — 0.968 ~196
GLM-5.3-Flash UD-IQ2_XXS (former deep tier, deleted) NVIDIA + RAM 0.971* 0.975 (0.988 at high effort) — — — ~3.6
GLM-5.2 int4 (Colibri) NVIDIA + RAM + both SSDs — — — — — ~0.4–0.6

* 7-category suite (before the 24-item bug set joined it). † 11-category suite without the 80-item bug set. ‡ Re-run with a 4,096-token limit (the first run gave both 0 on scripts and tests). Gemma 4 12B recovered; Qwen3.5 9B's long answers degenerate into runs of spaces on the NPU, so its low score is real. Test writing with a 4,096-token answer limit instead of 1,024: these models write long test files that the default limit cuts off mid-line (Qwen3.8-Flash-Next 2 → 5 of 9; DeepSeek-V4-Flash 0 → 1, its files run to 300–400 lines). Gemma 4 stays at 7 of 9 with the larger limit (49 s). Every Qwen3.8 variant writes 300–470-line test files and some wrong expectations, so test writing stays with Gemma 4. § Its 11-category score includes 0 on tests at the 1,024-token limit. Times, settings and the per-category scores are in the findings and the auto-generated tables.

Auto-generated results (every eval run)

Full suite, best first. Quality: score = mean of category scores (0–1). Speed: wall seconds for the whole suite, median decode (gen) and prompt (pp) tok/s.

model / config score endpoints apicalls json codegen codehard bugspot bughard secs gen tok/s pp tok/s
qwen36-35B-A3B IQ3 MTP (nv) THINK 0.914 1.00 1.00 0.99 1.00 1.00 0.80 0.60 430 183 1967
gemma-4-26B QAT +mtp (nv, 2x32k ub256 + cpu mmproj) 0.894 1.00 1.00 0.96 0.80 1.00 1.00 0.60 76 200 2083
qwen3.8-27B IQ4_XS +mtp (nv) THINK 0.885 1.00 1.00 0.99 1.00 1.00 0.80 0.40 794 50 872
qwen36 Q4_K_XL MTP ncmoe20 (nv+ram, 2x32k) 0.883 1.00 1.00 0.99 0.95 1.00 0.60 0.60 335 91 339
qwen36-35B-A3B Q4_K_XL (prod amd 890M) 0.878 1.00 1.00 0.99 0.95 1.00 0.60 0.60 239 19 493
qwen3-coder-next 80B-A3B UD-Q4_K_XL ncmoe (nv+ram) 0.861 1.00 1.00 0.98 1.00 1.00 0.80 0.40 517 32 237
Qwen3-Coder-30B-A3B UD-Q3_K_XL (nv) 0.838 1.00 1.00 0.99 1.00 1.00 1.00 0.80 304 106 2413
Qwen3.6-35B-A3B (npu flm) nothink 0.777 1.00 1.00 0.97 1.00 1.00 0.80 0.20 2300 18 87
Ornith-1.5-35B-A3B Q4_K_M (amd 890M) nothink 0.776 1.00 1.00 0.99 0.80 0.94 0.60 0.60 4788 12 251
Qwen3.5-9B Q4_K_M (rx7600 vk) think budget1024 0.773 1.00 1.00 0.99 1.00 0.90 0.40 0.60 3509 37 666
Qwen3.5-9B Q4_K_M (rx7600 vk) nothink 0.743 1.00 1.00 0.97 1.00 0.88 0.80 0.60 720 38 718
Ornith-1.5-35B-A3B IQ3_XXS (nv) nothink 0.723 1.00 0.98 0.92 0.80 1.00 0.60 0.40 463 112 2317
Ornith-1.5-9B Q4_K_M RX7600 + DFlash drafter 0.701 0.95 1.00 0.96 0.95 0.78 0.60 0.40 717 59 523
Ornith-1.5-9B Q4_K_M (rx7600 vk) nothink 0.698 0.95 1.00 0.97 0.95 0.88 0.60 0.40 897 37 684
gemma4-it:e4b (npu flm) 0.690 0.78 0.95 0.99 1.00 0.94 0.60 0.20 3134 12 421
MiMo-V2.6-Distill-Qwen-9B_Q4_K_M (rx7600 vk) nothink 0.652 0.95 1.00 0.96 0.73 0.78 0.60 0.60 673 36 728
Ling-3.0-tiny Q4_K_M (rx7600 vk) 0.604 1.00 0.99 0.98 0.88 0.94 0.40 0.20 361 84 1862
qwen3-it:4b (npu flm) 0.594 0.95 1.00 0.97 1.00 0.60 0.20 0.40 2801 17 463
Gemma-4-12B-it (npu flm) 0.592 0.78 0.98 0.67 1.00 0.94 0.80 0.60 961 6 281
LFM2.5-24B-A2B QAD-Q4_0 (nv) max3000 0.591 1.00 1.00 0.93 1.00 0.75 0.00 0.00 720 192 3870
Qwen3.5-9B (npu flm) nothink 0.555 0.97 0.92 0.88 0.80 0.50 0.80 0.60 2925 9 368
Llama-3.1-8B Q4_K_M (rx7600 vk) 0.541 0.97 0.93 0.79 0.67 0.72 0.40 0.60 414 45 790
Llama-3.1-8B (npu flm) 0.535 0.99 0.80 0.81 0.88 0.71 0.20 0.60 1545 12 375
K2-Horizon-3.7B_Q4_K_M (rx7600 vk) nothink 0.525 1.00 1.00 0.98 0.80 0.90 0.40 0.00 1395 58 1130
Mistral-Nemo-12B Q4_K_M (rx7600 vk) 0.524 0.40 0.96 0.99 0.80 0.68 0.80 0.00 671 30 500
DeepSeek-R1-Distill-Llama-8B Q4_K_M budget2048 (rx7600 vk) 0.461 0.95 0.71 0.67 0.47 0.60 0.40 0.40 3890 43 710
gpt-oss-20B (npu flm) 0.407 0.95 0.44 0.54 1.00 0.50 0.00 0.00 4146 20 191
DeepSeek-R1-Distill-Qwen-7B Q4_K_M budget2048 (rx7600 vk) 0.365 0.67 0.63 0.43 0.93 0.65 0.00 0.20 3016 47 760
phi4-mini-it:4b (npu flm) 0.352 0.28 0.93 0.96 0.27 0.51 0.20 0.40 3876 19 510
gemma4e-flash:e4b (npu flm) 0.338 0.10 0.00 0.33 0.80 0.88 0.20 0.20 1443 12 235
lfm25-1.2b-Q4_K_M 0.198 0.00 0.28 0.84 0.47 0.45 0.00 0.20 86 424 19332
LFM2.5-24B-A2B QAD-Q4_0 (nv) 0.192 0.80 0.00 0.33 0.40 0.00 0.00 0.00 373 155 3548
lfm25-1.2b-Q8_0 0.134 0.00 0.10 0.42 0.40 0.57 0.00 0.00 100 286 20138

Partial runs (subset of categories, older suite versions):

model / config score categories secs gen tok/s
qwen36-35b-a3b IQ3_XXS (nv, current fast) 0.759 endpoints 1.00, apicalls 1.00, bugspot 0.00, codegen 0.80, json 0.99 29 105
qwen36-35b-a3b IQ3_XXS nv (current fast) 0.879 endpoints 1.00, apicalls 1.00, bugspot 0.60, codegen 0.80, json 0.99 31 104
qwen36 IQ3 nv + ngram-mod spec 0.879 endpoints 1.00, apicalls 1.00, bugspot 0.60, codegen 0.80, json 0.99 38 104
qwen36 IQ3 MTP-GGUF nv + draft-mtp 0.919 endpoints 1.00, apicalls 1.00, bugspot 0.60, codegen 1.00, json 0.99 32 197
qwen36 MTP nv c65k np2 cpu-mmproj (candidate prod) 0.919 endpoints 1.00, apicalls 1.00, bugspot 0.60, codegen 1.00, json 0.99 34 196
PROD nv-main MTP 1.000 codegen 1.00 4 198
qwen3.8-27B IQ4_XS nv + mtp c16k 0.800 bughard 0.60, codehard 1.00 27 59
qwen3.8-27B IQ4_XS +mtp (nv) 0.825 scriptgen 0.83, scripthard 0.82 130 60
qwen36-35B-A3B IQ3 MTP (prod nv) 0.708 bugauto 0.71 27 163
qwen36-35B-A3B Q4_K_XL MTP (amd 890M vulkan) 0.917 bugauto 0.92 172 21
gemma-4-26B-A4B QAT Q4_K_XL +mtp (nv) 0.792 bugauto 0.79 24 188
GLM-5.3-Flash UD-IQ2_XXS ncmoe42 effort=low (nv+ram) 0.975 bugbig 0.97 5783 3
gemma-4-26B QAT +mtp (prod fast) 0.875 bugbig 0.88 94 186
qwen36 Q4_K_XL MTP (amd best, prod) 0.667 scriptgen 0.67 182 26
qwen36 IQ3_XXS MTP (old fast) 0.662 bugbig 0.66 91 163
Ternary-Bonsai-2-27B PQ2_0 (nv, prism fork) 0.800 bugbig 0.80 221 49
Nemotron-3.5-Bolt-74B-A9B 24GB (amd vulkan, b11706) 0.688 bugbig 0.69 1033 11
gemma-4-26B QAT +mtp (prod fast) THINK 0.050 bugbig 0.05 1847 182
qwen36 Q4_K_XL MTP (amd best) THINK 0.800 bugbig 0.80 8830 27
qwen36 Q5_K_S MTP (amd prod shape) 0.875 bugbig 0.88 440 25
qwen36 MXFP4_MOE MTP (amd prod shape) 0.875 bugbig 0.88 384 27
gemma-4-26B think budget256 (nv) 0.713 bugbig 0.71 594 188
gemma-4-26B think budget1024 (nv) 0.912 bugbig 0.91 589 189
qwen36 Q4_K_XL think budget256 (amd) 0.850 bugbig 0.85 1155 27
qwen36 Q4_K_XL think budget1024 (amd) 0.912 bugbig 0.91 3435 27
qwen36 Q4_K_XL think budget512 per-request (amd) 0.863 bugbig 0.86 2213 24
qwen36 Q4_K_XL think budget2048 per-request (amd) 0.963 bugbig 0.96 7180 24
GLM-5.3-Flash effort=high glm-sampling (nv+ram) 0.988 bugbig 0.99 16912 1
gemma-4-26B think budget2048 per-request (nv prod) 0.963 bugbig 0.96 988 187
gemma-4-26B (nv prod) scriptgen 0.917 scriptgen 0.92 29 196
gemma-4-26B effort=high (nv prod) scriptgen 0.833 scriptgen 0.83 91 192
qwen36 Q4 (amd prod) scriptgen 0.750 scriptgen 0.75 152 28
gemma-4-26B effort=max (nv prod) scriptgen 1.000 scriptgen 1.00 158 187
qwen36 Q4 effort=high (amd prod) scriptgen 1.000 scriptgen 1.00 752 27
qwen36 Q4 effort=max (amd prod) scriptgen 0.917 scriptgen 0.92 1050 26
qwen36 Q4 (amd prod) scripthard 0.727 scripthard 0.73 228 25
qwen36 Q4 (amd prod) scriptgen repair2 0.750 scriptgen 0.75 189 25
qwen36 Q4 (amd prod) scripthard repair2 0.818 scripthard 0.82 214 26
qwen3-coder-next 80B-A3B UD-Q4_K_XL ncmoe36 (nv+ram) 0.780 scriptgen 0.83, scripthard 0.73 749 15
qwen36-35B-A3B IQ3 MTP (old fast, nv) 0.780 scriptgen 0.83, scripthard 0.73 57 191
gemma-4-26B (nv prod) scripthard 0.727 scripthard 0.73 25 210
gemma-4-26B effort=max (nv prod) scripthard 0.818 scripthard 0.82 160 194
gemma-4-26B (nv prod) scriptgen checklist 0.750 scriptgen 0.75 31 204
gemma-4-26B (nv prod) scripthard checklist 0.818 scripthard 0.82 28 204
gemma-4-26B (nv prod) testgen 0.778 testgen 0.78 67 186
qwen36 Q4 (amd prod) testgen 0.333 testgen 0.33 680 30
Ornith-1.5-9B Q4_K_M (rx7600 vk) think budget1024 0.825 bugbig 0.82 3387 35
Ornith-1.5-35B-A3B IQ3_XXS (nv) think budget2048 0.801 bugauto 0.79, bugbig 0.89, scriptgen 0.75, scripthard 0.91, testgen 0.67 2168 113
qwen3.5:9b (npu flm) max4096 0.061 scriptgen 0.00, scripthard 0.18, testgen 0.00 4979 7
gemma4-it:12b (npu flm) max4096 0.650 scriptgen 0.67, scripthard 0.73, testgen 0.56 3085 7
DeepSeek-V4-Flash UD-IQ2_XXS ncmoe40 (nv+ram, fast SSD) 0.912 bugbig 0.91 2218 6
Qwen3.8-Flash-Next UD-Q2_K_XL ncmoe40 (nv+ram, fast SSD) nothink 0.900 bugbig 0.90 2009 18
DeepSeek-V4-Flash UD-IQ2_XXS ncmoe40 (nv+ram, fast SSD) tests-4096 0.111 testgen 0.11 4431 9
Qwen3.8-Flash-Next UD-Q2_K_XL ncmoe40 (nv+ram, fast SSD) nothink tests-4096 0.556 testgen 0.56 1426 16
Qwen3.8-Flash-Next UD-Q2_K_XL (nv+ram, fast SSD) 64K ncmoe40 nothink 1.000 bugauto 1.00 536 24
Qwen3.8-27B GSQ-RCO IQ3_S +mtp (nv, prod shape 2x32k+mmproj) 0.925 bugbig 0.93 206 60
Qwen3.8-Flash-Next GSQ-RCO-Coder IQ1_M ncmoe32 (nv+ram, fast SSD) nothink 0.963 bugbig 0.96 474 18
Qwen3.8-Flash-Next GSQ-RCO IQ2_XS ncmoe36 (nv+ram, fast SSD) nothink 0.975 bugbig 0.97 603 15
Nemotron-3.5-Super-VL UD-IQ2_XXS ncmoe80 (nv+ram, fast SSD) nothink 0.800 bugbig 0.80 874 14
gemma-4-26B QAT Q4_K_XL +mtp (nv) tests-4096 0.778 testgen 0.78 49 199
Qwen3.8-27B GSQ-RCO IQ3_S +mtp (nv, prod shape 2x32k) tests-4096 0.222 testgen 0.22 412 65
Qwen3.8-Flash-Next GSQ-RCO-Coder IQ1_M ncmoe32 (nv+ram, fast SSD) think budget2048 0.963 bugbig 0.96 4706 28
deep tier service: Qwen3.8-Flash-Next GSQ-RCO-Coder (llm deep start coder) 0.917 bugauto 0.92 182 17
Swift-1.5 Qwen3.8-Flash-Next GSQ-RCO IQ2_XS ncmoe36 (nv+ram, fast SSD) nothink 0.975 bugbig 0.97 1868 6
Qwen3.8-27B base IQ3_S-mtp effort=xhigh (nv 32k) 0.300 bugspot 0.60, bughard 0.00 57 52
Qwen3.8-27B swift IQ3_S-mtp effort=xhigh (nv 32k) 0.800 bugspot 0.80, bughard 0.80 967 52
Qwen3.8-27B swift IQ3_S-mtp effort=low (nv 32k) 0.900 bugspot 1.00, bughard 0.80 423 60
Qwen3.8-27B swift IQ3_S-mtp nothink (nv 32k) 0.800 bugspot 1.00, bughard 0.60 26 64
Qwen3.8-27B base IQ3_S-mtp effort=xhigh rerun (nv 32k) 0.800 bugspot 0.80, bughard 0.80 1436 50
Qwen3.8-27B base IQ3_S-mtp effort=low rerun (nv 32k) 0.900 bugspot 1.00, bughard 0.80 237 60
Qwen3.8-27B base IQ3_S-mtp effort=nothink rerun (nv 32k) 0.800 bugspot 1.00, bughard 0.60 26 64
Swift-1.5 Qwen3.8-Flash-Next GSQ-RCO IQ3_XXS ncmoe40 (nv+ram, fast SSD) nothink 0.975 bugbig 0.97 2011 4
Swift-1.5 Qwen3.8-27B IQ3_XXS-mtp (nv 64k) xhigh 0.800 bugspot 0.80, bughard 0.80 963 55
Swift-1.5 Qwen3.8-27B IQ3_XXS-mtp (nv 64k) nothink 0.800 bugspot 1.00, bughard 0.60 28 67
Swift-1.5 Qwen3.8-Flash-Next GSQ-RCO Q2_0 ncmoe32 (nv+ram, fast SSD) nothink 0.900 bugbig 0.90 2269 9
Swift-1.5 Qwen3.8-Flash-Next GSQ-RCO IQ3_S ncmoe40 (nv+ram, fast SSD) nothink 0.975 bugbig 0.97 1594 6
Swift-1.5 Qwen3.8-27B IQ3_XXS +mtp (nv, prod shape 2x32k+mmproj) 0.900 bugbig 0.90 212 63
Swift-1.5 Qwen3.8-27B IQ3_XXS +mtp (nv, prod shape 2x32k+mmproj) tests-4096 0.278 testgen 0.28 373 73
Swift-1.5 Qwen3.8-27B IQ3_XXS +mtp (nv, prod shape 2x32k+mmproj) low-effort 0.971 bugauto 1.00, bugbig 0.97, scriptgen 1.00, scripthard 0.91 2265 64
Qwen3.8-27B base GSQ-RCO IQ3_XXS +mtp (nv 2x32k) low-effort 0.983 bugauto 0.96, bugbig 0.97, scriptgen 1.00, scripthard 1.00 2358 63
kunthawat Swift-1.5 Qwen3.8-27B IQ3_XXS +mtp (nv, prod shape 2x32k+mmproj) 0.925 bugbig 0.93 208 63
kunthawat Swift-1.5 Qwen3.8-27B IQ3_XXS +mtp (nv, prod shape 2x32k+mmproj) tests-4096 0.222 testgen 0.22 334 70
kunthawat Swift-1.5 Qwen3.8-27B IQ3_XXS +mtp (nv, prod shape 2x32k+mmproj) low-effort 0.940 bugauto 0.96, bugbig 0.97, scriptgen 0.92, scripthard 0.91 1881 60
Muse-Glimmer-30B UD-IQ3_XXS (nv 32k) strength=low 1.000 bugbig 1.00 1374 30
gpt-oss-20b MXFP4 (nv 2x32k) effort=low 0.812 bugbig 0.81 138 127
Devstral-Small-2-24B IQ4_XS (nv 32k) 0.650 bugbig 0.65 179 30
Devstral-Small-2-24B IQ4_XS (nv 32k) tests-4096 0.556 testgen 0.56 347 30
Muse-Glimmer-30B UD-IQ3_XXS +dflash (nv 64k) strength=medium 0.988 bugauto 1.00, bugbig 0.97 2548 52
Strata coder-iq1m lowram nothink 0.900 bugbig 0.90 276 60
Qwen3.8-27B UD-IQ4_XS video recipe ngl60 64K q4kv mtp2 nothink 0.938 bugbig 0.94 384 16
Qwen3.8-27B UD-IQ4_XS video recipe ngl60 64K q4kv mtp2 think 0.800 bugspot 0.80, bughard 0.80 3619 16
Ornith-1.5-122B UD-IQ3_XXS ncmoe40 64K (nv+ram) nothink 0.900 bugbig 0.90 1447 6
Strata swift15-fn-iq2xs lowram nothink 0.925 bugbig 0.93 341 108
Strata swift15-fn-iq3xxs lowram nothink 0.963 bugbig 0.96 436 91
Strata qwen38-flash-next-iq2xs lowram nothink 0.925 bugbig 0.93 351 111
Strata qwen36-35b-a3b-ud-q4kxl lowram nothink 0.875 bugbig 0.88 334 79
MiMo-V2.6-Distill-Qwen-9B_Q4_K_M (rx7600 vk) think budget1024 0.438 bugbig 0.44 1802 36
K2-Horizon-3.7B_Q4_K_M (rx7600 vk) think budget1024 0.150 bugbig 0.15 1516 56
Muse-Glimmer-30B EXL3 3.50bpw +assistant dyn (exllamav3 tabby, nv 64k) strength=medium 0.768 bugauto 0.75, bugbig 0.79 1532 58
Qwen3.8-Flash-Next EXL3 2.05bpw_h4_ng4 split400 (exllamav3 tabby, nv+ram, 890M off) nothink 0.963 bugbig 0.96 357 39
Raw speed sweeps (llama-bench)
time model ncmoe extra pp tok/s tg tok/s
2026-10-15 21:39:28 GLM-5.3-Flash-UD-IQ2_XXS 99 15.3 2.97
2026-10-15 21:43:48 GLM-5.3-Flash-UD-IQ2_XXS 99 -ub 2048 -b 2048 41.6 2.78
2026-10-15 21:48:50 GLM-5.3-Flash-UD-IQ2_XXS 44 -ub 2048 -b 2048 54.5 3.04
2026-10-15 21:52:15 GLM-5.3-Flash-UD-IQ2_XXS 42 -ub 2048 -b 2048 52.3 3.6
Second SSD and the GLM-5.2 rerun

The second SSD speeds up models that stream from disk. The Samsung 9100 PRO reads at 7.2 GB/s (a PCIe 5 drive held to PCIe 4 x4 by the slot) against the WD's 4.7 GB/s. GLM-5.3-Flash deep tier, llama-bench, cold page cache:

model files on prefill decode
Samsung 24.3 2.91
split across both drives 18.8 2.53
WD 15.6 2.38

Splitting the shards across both drives is slower than the Samsung alone: llama.cpp waits on the slower drive. So only the models that stream (bigger than RAM) live on the Samsung; everything that loads fully into GPU or NPU memory went back to the WD.

GLM-5.2 on Colibri, rerun on the fast SSD: 0.31 → 0.50 tok/s, still unusable. Best cold setup: CUDA, model on the Samsung, a 248 GB partial mirror of the most-used experts on the WD (COLI_MODEL_MIRROR), direct reads and pipelined loading (DIRECT=1 PIPE=1); 28% of expert bytes came from the mirror. Part of each step's gain is Colibri learning which experts to pin (hit rate 18% → 35%). Details in the GLM log below.

  • Vulkan beats CUDA here: 0.60 tok/s on the 5060 Ti with Vulkan, against 0.42 with CUDA in the same cold setup. Adding the RX 7600 as a second Vulkan device gave nothing (0.61). Colibri's launcher flags --gpu and --vram switch on CUDA, which the Vulkan engine refuses; use --gpu none and size the Vulkan expert tier with COLI_VK_TIER_GB.
  • Warming up doesn't help: 8 requests in one CUDA process ran at 0.44 tok/s for the first and 0.41 on average for the last four.

GLM-5.2 (744B) isn't viable here, on Colibri or on llama.cpp.

  • Decode runs at 0.3 tok/s on CPU, CUDA, and with 28 or 44 GB RAM. The single NVMe limits it, because only about 8% of experts can be cached.
  • Rerun on 2026-10-18 with a second, faster SSD: 0.50 tok/s at best (finding 3). Still about 20 minutes for a 500-token answer.
  • Prefill of a 19K-token diff didn't finish layer 1 of 78 in 13 minutes.
  • The smallest GGUF is 217 GB, about 3× RAM plus VRAM.
  • Deleted (429 GB) after the first test; downloaded again for the SSD rerun.
GLM on this machine: detailed log
GLM-5.2 (744B MoE, about 40B active) on Colibri v2.0.0#
  • Engine: JustVugg/colibri v2.0.0, an MoE engine that streams experts from NVMe.
  • Trust check: about 42k stars, and every published advisory affects ≤1.4.0 only.
  • Builds: colibri-cpu, colibri-cuda (CUDA=1 CUDA_ARCH=sm_120, CUDA 13.0) and colibri-vk.
  • CUDA toolkit: NVIDIA's ubuntu2404 apt repo, cuda-toolkit-13-0 (nvcc 13.0.88).
  • Weights: mastouri/GLM-5.2-colibri-int4-g64-with-int8-mtp.
  • 429 GB, 142 Colibri-format safetensors shards: int4 experts plus an int8 MTP head.
  • About 2 hours to download with start-here.sh --model glm-5.2 --backend cpu.
  • Gotcha: after the download, start-here.sh launches its own coli web server on :8000 (CPU). Kill it before starting a managed service.
  • Colibri's own plan for this box:
  • Dense part: 11.9 GB in RAM.
  • Expert cache: 17.8 GB (10 per layer).
  • Projected expert hit rate: 8%.
  • Service: coli serve --model <model dir> --host 127.0.0.1 --port 8000 --gpu auto --vram 14 --ram 28 --auto-tier --ctx 32768 --no-think It swaps with the NVIDIA llama-server because both need the 16 GB card.

Decode benchmark (48-token TypeScript prompt, temp 0, identical output in every run):

backend RAM budget expert placement time to first token decode
CPU (setup default) 37 GB auto 0 VRAM + 125 RAM 47.5 s 0.29 tok/s
CUDA sm_120, --vram 14 28 GB 652 VRAM + 8 RAM 3.6 s (warm 2.8 s) 0.31 tok/s
CUDA, AMD services stopped 44 GB 652 VRAM + 106 RAM 3.5 s 0.32 tok/s

Rerun with a second SSD (2026-10-18). Same engine build, CUDA, --vram 14 --ram 28, a 26-token code prompt, 48 tokens out, each run a fresh process:

model files I/O mode prefill decode expert hit rate
Samsung (7.2 GB/s) buffered (October setup) 45 s 0.33 tok/s 18%
Samsung DIRECT=1 PIPE=1 27 s 0.42 tok/s 28%
Samsung URING=1 DIRECT=1 26 s 0.47 tok/s 33%
Samsung + 248 GB WD mirror DIRECT=1 PIPE=1 22 s 0.50 tok/s 35%
  • The mirror served 28% of expert bytes; about 2 s per token (p50 2.06 s).
  • The hit rate rises run to run because Colibri pins the experts it has seen used (.coli_usage), so part of each gain is learning, not the disk.
  • Colibri's Vulkan engine needs COLI_VULKAN=1 to use a GPU (without it, it runs on the CPU and prints no [VK] ready line), and its server only accepts the model id /v1/models lists.

Observations:

  • Decode is disk-bound.
  • Each token needs about 40B active parameters, and with ~8% cache hits most experts stream from one WD SN740 NVMe.
  • CUDA cut time to first token 13×, but decode didn't move.
  • Adding RAM (28 → 44 GB) barely changed the hit rate.
  • MTP speculation was left off (COLI_CUDA_MTP=0, logs show draft=0). Colibri's docs measure it as a net loss below about 99% expert residency.
  • Prefill is the real blocker.
  • First real task: a review of a 19,349-token diff. After 13 minutes it was still on layer 1 of 78.
  • The work was CPU-bound: 51% CPU, no IO wait.
  • RAM ran out (about 5 GB in swap).
  • Projected time was many hours, so it was killed.
  • For comparison, Colibri's README reports GLM-5.2 at:
  • 0.05–0.1 tok/s cold on a 25 GB laptop
  • 1.83 tok/s on a 128 GB Ryzen AI Max+ 395
  • 9 tok/s on 6× RTX 5090
  • Harness changes made while testing:
  • At 0.3 tok/s, a synchronous tool call times out after about 180 tokens, so deep requests became detached jobs that write the answer to a markdown file.
  • Jobs refuse prompts over 8,000 characters.
  • GLM-5.2 on llama.cpp instead:
  • The Colibri files can't be loaded by llama.cpp.
  • The smallest GGUF (Unsloth UD-IQ1_S) is 216.7 GB, about 3× RAM plus VRAM, so it would hit the same disk-streaming limit. Not downloaded.
  • Decision: GLM-5.2 was deleted to free 429 GB.
  • What would make GLM-5.2 viable:
  • 128 GB or more of RAM.
  • A second NVMe: the README's 1.5 tok/s DeepSeek-V4-Flash rig used two.
  • Or the hosted API.
GLM-5.3-Flash (320B / 18B active, hybrid sparse + linear attention, natively multimodal)#
  • Vendor claim: better than GLM-5.2 on agentic coding. DeepSWE 63.4 vs 46.2; Toolathlon 78.4 vs 59.9. These are vendor-reported, not verified here.
  • Colibri: supports it in int4: a 328 GB download converted to 195 GB. The README reports about 20 s per token warm with 25 GB of RAM. Not tried: it would be disk-bound like GLM-5.2.
  • llama.cpp: support merged in PR #27773 on 2026-09-30.
  • The Unsloth model card still links the closed PR #27754, but build b11642 already includes the glm5-next architecture.
  • Unsloth GGUF sizes:
quant size
UD-IQ1_S 93.1 GB
UD-IQ1_M 97.6 GB
UD-IQ2_XXS (used) 101.8 GB
UD-Q2_K_XL 108.7 GB
UD-IQ3_XXS 120.4 GB

A third-party IQ1_M at 65 GiB fails the trust check (2 likes). - Download: about 25 minutes at ~70 MB/s, as 4 resumable parallel shards. - llama-bench (CUDA, -ngl 99, experts kept in RAM except the last ncmoe layers, KV q8_0), with prompt-processing (pp) and decode (tg) speeds in tok/s:

-ncmoe batch pp tg note
99 (all experts in RAM) default 512 15.3 2.97
99 -ub 2048 -b 2048 41.6 2.78 bigger batches amortize streaming experts over PCIe
44 -ub 2048 -b 2048 54.5 3.04
42 -ub 2048 -b 2048 52.3 3.60 best
40 / 36 -ub 2048 -b 2048 — — out of memory (ncmoe 36 needed 24.8 GB on the GPU; about 2 GB per expert layer)
  • Thinking can't be disabled. The chat template sets reasoning_effort to max unless given low or high. This matches Z.ai's GLM-5.3 notes: "Disabling thinking is no longer supported", with levels low, high and max, and max recommended for coding. At 3.6 tok/s, thinking tokens dominate latency, so evals use reasoning_effort=low.
  • Verdict so far: about 12× GLM-5.2's decode speed and a much faster prefill (a 19K-token prompt takes about 6 minutes). Usable only for batch or overnight jobs. Quality eval pending.
GLM-5.3 (full model)#
  • Per Z.ai's GLM-5.3 post, the weights were due "in two weeks". It's the same 744B class as GLM-5.2, so the conclusions above apply.
  • Hosted access: the GLM Coding Plan, which works with Claude Code and other agents, with off-peak usage at 50% of points.
Baseline: Qwen3.6-35B-A3B on each chip

Measured with llama-bench b11642, -fa 1. Speeds are in tok/s: prompt-processing at 512 and 4,096 tokens (pp512, pp4096) and decode (tg128).

Config pp512 pp4096 tg128
NVIDIA, UD-IQ3_XXS (12.3 GB), fully in VRAM 2652 2612 109.7
NVIDIA, UD-Q4_K_XL (20.8 GB), -ncmoe 16 (16 layers of experts in RAM) 521 515 31.6 ±14
NVIDIA, Q4_K_XL, -ncmoe 8 / 12 OOM OOM OOM
AMD 890M (Vulkan/RADV), UD-Q4_K_XL 586 554 19.7
AMD 890M, UD-IQ3_XXS 477 n/a 25.2
NVIDIA, UD-IQ3_XXS + MTP (--spec-type draft-mtp) ~2000 ~196

Decisions:

  • The NVIDIA card serves the fast tier, with a quant that fits fully in VRAM. Pushing experts into RAM to fit Q4 makes it CPU-bound, and the GPU's 5× advantage disappears.
  • The AMD iGPU serves the "best" tier with the same model at Q4. Using the same model family on both chips keeps answers consistent and lets either side take over if the other fails.
  • On this chip, ROCm/HIP is slower than Vulkan, as reported in llama.cpp #20099.
Ubuntu setup, patches and build gotchas

System:

Component Version
OS Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic
NVIDIA driver nvidia-driver-595-server-open 595.91.07 (with matching nvidia-utils-595-server)
eGPU link OCuLink, PCIe Gen4 x4
CUDA toolkit cuda-toolkit-13-0 13.0.3 (nvcc 13.0.88), from NVIDIA's ubuntu2404 apt repo. NVIDIA has no 26.04 repo yet, and the 24.04 packages install cleanly.
Vulkan Mesa 26.0.8 RADV (mesa-vulkan-drivers), libvulkan-dev 1.4.341, glslc 2026.1
NPU amdxdna in-kernel driver, firmware 1.1.2.64 from linux-firmware 20260319
Runtimes Python 3.11, Node 24, Bun 1.3, Docker 29

AI stack (all in user space, no root):

  • llama.cpp b11642 prebuilt release binaries, two builds side by side:
  • Vulkan, for the AMD iGPU.
  • CUDA 12.8, for NVIDIA.
  • Colibri built from source three ways: CPU, CUDA (CUDA 13.0, sm_120) and Vulkan.
  • Services are systemd --user units with linger enabled, so they start at boot with no login:
  • llm-nv-main (:8093)
  • llm-amd-main (:8091)
  • llm-amd-embed (:8092)
  • llm-deep (:8000; off by default, swaps with llm-nv-main)
  • Idle memory: every llama-server uses --sleep-idle-seconds 1800, which frees VRAM and RAM when idle.

Patches and workarounds that were needed:

  1. Driver mismatch after installing utils. Installing nvidia-utils-595-server removed the 580 kernel modules. The fix was installing the matching nvidia-driver-595-server-open.
  2. OCuLink eGPU isn't hot-pluggable. Power the dock before a cold boot, or the card isn't on the PCIe bus.
  3. CUDA runtime for the llama.cpp CUDA build. The prebuilt binary needs libcudart.so.12, libcublas.so.12 and libcublasLt.so.12. These were copied from NVIDIA's cudart and cuBLAS redistributables into the binary directory, and units set LD_LIBRARY_PATH to it. - Copying the libraries while the tarball was still extracting caused a bus error. Copy only after extraction completes.
  4. Driver 595 ships CUDA 13.x, but the llama.cpp build is CUDA 12.8. It works through the driver's forward compatibility, and Blackwell (sm_120) is supported.
  5. Vulkan picks the wrong GPU when the eGPU is attached. Pin the Radeon by pointing VK_DRIVER_FILES at the RADV ICD file. On 26.04 it's named radeon_icd.json, not radeon_icd.x86_64.json.
  6. ROCm/HIP vs Vulkan: Vulkan (RADV) is faster than ROCm on the 890M (gfx1150), as reported in llama.cpp #20099, so ROCm isn't installed.
  7. Playwright refuses Ubuntu 26.04. Install the browsers with: PLAYWRIGHT_HOST_PLATFORM_OVERRIDE=ubuntu24.04-x64 npx playwright install chromium-headless-shell chromium Screenshots and UI audits depend on this.
  8. Running sudo from an AI agent: sudo can't prompt for a password through the agent's shell. Run privileged steps in a separate SSH session: - the driver - the CUDA repo and toolkit - libvulkan-dev and glslc (needed for Colibri's Vulkan build) - linger
  9. The NPU needs one root step. Install Ubuntu's libxrt2/libxrt-npu2 plus FastFlowLM's .deb, and raise memlock to unlimited (see the NPU section). No PPA or DKMS on Ubuntu 26.04 with kernel 7.0.
  10. Colibri's start-here.sh auto-starts a server on :8000 after downloading. Stop it before starting the managed llm-deep unit.

Build and ops gotchas#

  • Two llama.cpp builds live side by side:
  • Vulkan, for AMD.
  • CUDA 12.8, for NVIDIA, with the cudart libraries copied in.
  • Bus error in the CUDA build: caused by copying the cudart libraries while the tarball was still extracting. Copy only after extraction finishes.
  • Vulkan device choice: with the eGPU attached, Vulkan must be pinned to the Radeon with VK_DRIVER_FILES (the RADV ICD file).
  • OCuLink eGPU isn't hot-pluggable: cold-boot with the dock already powered.
  • MCP server edits: a syntax error in the MCP server once made /mcp reconnect fail silently. A smoke test (handshake plus tools/list) now runs before every harness commit.

Sources#