Journal

Everything Is Becoming Rust: The AI Compiler Loop, Discord's Client Shift, and How We Rewrote Kuro into a 14.2 MB Bare-Metal Voice Engine

Why the industry is rewriting everything in Rust—from Discord's client to local AI—and how we rebuilt Kuro as a 14.2 MB native Windows voice engine with AVX2 routing, Kokoro TTS, and zero-Python STT.

A
8 min read
Everything Is Becoming Rust: The AI Compiler Loop, Discord's Client Shift, and How We Rewrote Kuro into a 14.2 MB Bare-Metal Voice Engine
Kuro brand mark on paper
Kuro — local-first Windows desk voice agent

If you have spent any time on engineering forums lately, the pattern is hard to miss: everything known to software is being ported to Rust.

Game engines. Creative tools. Minecraft servers. Discord's client path. And across local AI — including our own desk agent, Kuro — teams are ripping out Python and Electron for native Rust.

Why Rust, and why now? The honest answer is not raw speed alone. Large language models changed how code is written. Local AI changed what consumer hardware can tolerate. Rust sits at the intersection of both pressures.

1. Why everything is shifting to Rust

For a decade the knock against Rust was simple: too hard, too slow to write. Startups shipping a desktop UI by Friday reached for TypeScript and Electron. Machine learning reached for Python.

AI-assisted coding flipped those economics overnight.

The compiler as a deterministic harness

LLMs are probabilistic token predictors. They hallucinate. They work best when smashed against an uncompromising verifier.

  • C / C++ — Clean compiles can still hide undefined behavior, leaks, and use-after-free. Debugging burns tokens and hours after the fact.
  • Python / JavaScript — Loose feedback loops and training slop mean many runtime revisions for bugs a type system would reject once.
  • Rust — Ownership, the borrow checker, and Send/Sync kill whole bug classes before a binary runs — especially when unsafe_op_in_unsafe_fn is denied at the workspace level.

The AI + rustc verification loop

LLM agentProbabilistic draft. Fast, imperfect, endlessly iterable.
rustc + clippyDeterministic verifier. Readable diagnostics. Tight loop.
Ship binaryMemory-safe artifact without waiting for production crashes.

Failure modes elsewhere · C/C++ silent UB after a clean compile · Python/JS runtime exceptions after N revisions

Figure 1 — Probabilistic agents need a strict compiler feedback loop

The warehouse air-conditioning irony

For twenty years engineers begged for strict compilers, clean CLIs, actionable errors, and real documentation. Management rarely cared — until agents needed those exact guardrails to stop hallucinating broken code. Same story as warehouses that refused air conditioning for people, then installed it overnight for robots that overheated.

Type-driven correctness

Rust's deeper advantage for long-lived systems is logic that refuses to drift. Exhaustive match and zero-cost newtypes catch missing variants and unit mixups at compile time:

#[derive(Debug, Clone, Copy)]
pub struct ResistancePct(pub f32);

pub enum DamageType {
    Fire { initial: f32, dot_per_sec: f32, duration_secs: f32 },
    Ice { slow_ratio: f32 },
    Psy,
    Nuke,
    Physical,
}

pub fn compute_resistance(received: &DamageType) -> ResistancePct {
    match received {
        DamageType::Fire { .. } => ResistancePct(10.0),
        DamageType::Ice { .. } => ResistancePct(10.0),
        DamageType::Psy => ResistancePct(5.0),
        DamageType::Physical => ResistancePct(25.0),
        // rustc: missing DamageType::Nuke
    }
}

Forget Nuke in C or a scripting language and you may corrupt state quietly. In Rust the build fails. Add Wind six months later and rustc lists every call site that must change. Pair that with cargo instead of sprawling CMake trees, and you get forty years of systems lessons without forty years of baggage.

2. Discord and the end of the Electron tax

Everyone complained about Electron. Almost everyone shipped it — because TypeScript and React made polished cross-platform UI cheap.

Open an Electron app once a week and you shrug. Keep Teams, Slack, or Discord open all day — hundreds of interactions beside local AI models — and Chromium plus a GC in every desktop process becomes painful. Java, C#, and Go on the client bring their own runtime or stutter costs for real-time audio and video.

Discord already used Rust on the backend and in native modules for predictable latency. Moving more of the client experience toward Rust is the bellwether: when RAM is scarce and startup must feel instant, native wins.

3. Enter Kuro — rewriting the desk agent in native Rust

We did not watch from the sidelines. We hit the same walls building Kuro.

Kuro speaking tray mark
Kuro mark — speaking pose from the native tray brand set

Hold Ctrl+Alt+Space, speak, release. KuroShell (WinUI 3 / .NET 10 x64) is a quiet always-on-top capsule. kuro-engine.exe owns the hotkey, Whisper, routing, tools, and speech.

  • Desk hardware — Tuya TCP plugs for monitors and lights: desk on, desk off, good night, and early wake up daddy's home while the hotkey is still held.
  • Agency — n8n mail triage, RSS (The Verge, Hacker News, BBC, NPR), Google Meet via native OAuth, WhatsApp contact resolution.
  • Local multimodal — Win32 GDI capture (GetDC, BitBlt, GetDIBits) into qwen3-vl:8b, plus multi-turn chat on Ollama at 127.0.0.1:11434.

KuroShell brand poses

Idle IdleQuiet mark
Listening ListeningHotkey held
Processing ProcessingSTT + route
Speaking SpeakingKokoro audio

Figure 2 — Paper / ink tray marks from the Kuro brand kit

Why Python 3.11 hit the wall

The legacy stack was classic: faster-whisper, Coqui XTTS-v2, FastAPI, pynput — 29 Python files. On an 8 GB VRAM laptop it meant:

  1. 1.8–3.5 GB committed for Python + PyTorch + XTTS, colliding with Whisper and Ollama.
  2. WH_KEYBOARD_LL via pynput — every OS keystroke through the interpreter.
  3. Hidden STT latency — whisper_worker.py at 1,640–1,765 ms warm for a single word.
  4. Brittle phrases — .contains("help me") hijacked long coding prompts into the static help menu.

We quarantined the Python tree under legacy/python/ and built kuro-rs: a nine-crate Rust 2024 workspace.

kuro-rs workspace · Named pipe + local API

KuroShell WinUI 3 capsule · tray · starts kuro-engine.exe with KURO_API=on

\\.\pipe\KuroEngine · 127.0.0.1:8765

core
ipc
hotkey
audio
stt
router
tools
tts
wifi

Figure 3 — Nine crates behind a 14.2 MB idle working set

4. Inside kuro-rs — math, SIMD, neural path

3-tier semantic router (kuro-router)

Hardcoded substrings died. The hybrid router:

  • Tier 1 — O(1) exact hash for ≤3-token reflex commands. Never .contains() on long sentences.
  • Tier 2 — In-process BAAI/bge-small-en-v1.5 ONNX with a 60-line pure-Rust WordPiece tokenizer and dynamic [1, actual_seq_len] tensors.
  • Tier 3 — Conversational margin gating plus Jaro-Winkler (≥ 0.86) for contacts.

An AVX2 + FMA kernel scores 384-d dots in 0.62 ns — full exemplar pass in 0.151 µs:

#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx2,fma")]
pub unsafe fn dot_384_avx2(a: &[f32; 384], b: &[f32; 384]) -> f32 {
    use std::arch::x86_64::*;
    unsafe {
        let mut acc0 = _mm256_setzero_ps();
        let mut acc1 = _mm256_setzero_ps();
        let mut acc2 = _mm256_setzero_ps();
        let mut acc3 = _mm256_setzero_ps();
        let ap = a.as_ptr();
        let bp = b.as_ptr();
        let mut i = 0usize;
        while i < 384 {
            acc0 = _mm256_fmadd_ps(_mm256_loadu_ps(ap.add(i)), _mm256_loadu_ps(bp.add(i)), acc0);
            acc1 = _mm256_fmadd_ps(_mm256_loadu_ps(ap.add(i + 8)), _mm256_loadu_ps(bp.add(i + 8)), acc1);
            acc2 = _mm256_fmadd_ps(_mm256_loadu_ps(ap.add(i + 16)), _mm256_loadu_ps(bp.add(i + 16)), acc2);
            acc3 = _mm256_fmadd_ps(_mm256_loadu_ps(ap.add(i + 24)), _mm256_loadu_ps(bp.add(i + 24)), acc3);
            i += 32;
        }
        let total = _mm256_add_ps(_mm256_add_ps(acc0, acc1), _mm256_add_ps(acc2, acc3));
        let sum128 = _mm_add_ps(_mm256_castps256_ps128(total), _mm256_extractf128_ps(total, 1));
        let sums = _mm_add_ps(sum128, _mm_movehdup_ps(sum128));
        _mm_cvtss_f32(_mm_add_ss(sums, _mm_movehl_ps(sums, sums)))
    }
}

Kokoro-82M on ort (kuro-tts)

Eight local TTS options scored on naturalness, Rust fit, latency, VRAM, and flexibility. Kokoro-82M won. We bypassed the broken kokoro-en wrapper and run kokoro-v1.0.onnx on the workspace-pinned ort crate.

ModelMemoryCPUScore
Kokoro-82M~180–320 MB ONNXYes83
PiperMinimalYes76
Qwen3-TTSUnverifiedUnlikely72
Chatterbox Turbo~4.5–5 GBSlow70
XTTS-v2 (legacy)~4–6 GBSlow65
Orpheus 3B~8 GB+No63

A 3-token warm-up at init drops first audio from 1315 ms cold to 302 ms warm. Desk rituals cache to < 2 ms.

Zero-Python STT (kuro-stt + kuro-audio)

In-process whisper-rs first regressed to 17.6 s warm. Fixes: MSVC /arch:AVX2 for ggml C++, Silero VAD trim, dynamic audio_ctx, persistent WhisperState, greedy decode with temperature_inc = 0.0. Capture writes a lock-free rtrb SPSC ring — no mutex in the WASAPI callback.

let duration_secs = (trimmed_audio.len() as f32) / 16_000.0;
let raw_ctx = ((duration_secs * 50.0) as i32) + 64;
let audio_ctx = ((raw_ctx + 63) / 64 * 64).clamp(128, 1500);

let mut params = FullParams::new(SamplingStrategy::Greedy { best_of: 1 });
params.set_audio_ctx(audio_ctx);
params.set_temperature(0.0);
params.set_temperature_inc(0.0);
params.set_single_segment(true);

0.0% idle CPU and 0.2 MB dormant

When the capsule is quiet, the 30 Hz event loop parks on tokio::sync::Notify. Off home Wi-Fi, kuro-wifi drops Whisper and ONNX sessions, runs _heapmin() and K32EmptyWorkingSet — 705.7 MB → 0.2 MB. The seven-stage gate (Test-KuroGate.ps1) denies warnings, emoji, and secret leaks.

[profile.release]
opt-level = 3
lto = "fat"
codegen-units = 1
panic = "abort"
strip = "symbols"

[workspace.lints.rust]
warnings = "deny"
unsafe_op_in_unsafe_fn = "deny"

5. Scorecard — Python stack vs kuro-rs

Measured deltas

Idle RAM 14.2 MB
Dormant 0.2 MB
Cold boot 736 ms
Footprint 8.6 MB
384-d dot 0.62 ns

Figure 4 — From multi-GB Python commit to a bare-metal desk engine

DimensionPython 3.11kuro-rs + KuroShell
Engine footprintMulti-GB venv8.6 MB exe
Idle RAM1.8–3.5 GB14.2 MB
DormantResident0.2 MB
Cold start4–9 s736 ms
Intent mathSubstring rules0.62 ns AVX2
TTS first audio400–600 ms XTTS<2 ms cache / 302 ms warm
Idle CPU / hookpynput LL hook0.00% + RegisterHotKey

The carcinisation of software is not a meme. Explore the source: github.com/aryan-dani/Kuro.