As a Developer, This Is How I’d Introduce WSL Dashboard #14302
Unanswered
owu
asked this question in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
I’ve always seen WSL as one of the best-value capabilities on Windows: lightweight, fast, and close enough to a native Linux experience for real work. But in day-to-day use, managing WSL can easily get slowed down by a lot of small commands and workflows: checking status, switching the default distro, migrating disks, cloning for backups, exporting archives… all doable, but not very intuitive, and not ideal for high-frequency usage.
So I built WSL Dashboard: a WSL management panel designed around everyday workflows. The goal isn’t to “wrap every command with a GUI”, but to turn the most common, most error-prone, and most time-consuming paths into a product-grade experience that’s visual, recoverable, and maintainable over time.
Project: https://github.com/owu/wsl-dashboard
What I’m Building
WSL Dashboard is a modern native desktop app: Rust + Slint + Skia + Tokio (see Cargo.toml). Its core capabilities include:
If you think of it as a “graphical console for WSL”, you’ll probably find it’s closer to a workflow-polished product: it reduces command memorization, avoids pitfalls in heavy operations like move/clone, and keeps system state and UI state aligned as much as possible.
Why It Stays Smooth (and Hard to Freeze)
The core performance strategy of WSL Dashboard is to fully isolate “slow, uncertain, potentially hanging” work from the UI thread, and to enforce strict constraints on concurrency and refresh frequency.
1) All WSL calls are async, with controlled concurrency
Under the hood, WSL operations are executed via
wsl.exe. But I don’t want a single slow command to make the UI unusable, so the execution layer implements several key safeguards (see executor.rs):wsl.exeviatokio::process::Command, reads stdout/stderr without blocking.kill_on_drop(true)so timeouts/cancellation won’t leave “zombie wsl.exe” processes.The goal isn’t “faster at all costs”, but “the UI should not get dragged down no matter how you use it”.
2) Refresh is event-driven, with throttling
Another major source of UI jank is refresh logic: frequent refresh → frequent commands → frequent model updates → UI pressure. Here, refresh is handled along two paths (see tasks.rs and wsl/dashboard/mod.rs):
Meanwhile,
WslDashboardmaintains a “manual heavy operation” counter and a “heavy-op lock”, so background refresh won’t interfere with long-running move/clone operations—and it performs a final sync when operations finish.Internationalization Is Not Just “A Translation Table”
In v0.4.0, I treated i18n as a full engineering effort: resource organization, build-time integrity checks, and UI-level RTL/font strategies all need to form a closed loop.
1) Resource organization + loading: English fallback + language overrides
assets/i18n/*.toml, and are embedded into the binary via RustEmbed at runtime (see i18n/mod.rs).zh-Hans/zh_CN) to reduce mismatches caused by system locale differences.2) Build-time integrity checks: missing keys are surfaced during build
I don’t want i18n quality to rely solely on manual checking, so the build script includes an i18n integrity check (see build.rs): it uses
en.tomlas the baseline, scans all language files, and prints warnings for missing keys. This helps catch translation gaps early before release.3) RTL + complex-script UI strategy
RTL support isn’t just “right-align the text”. Many layouts need mirroring, and padding/icon/text placement and title-bar control ordering must stay consistent. The project uses a global
AppI18n.is-rtlswitch to branch UI behavior (see theme.slint and Slint components).Also, complex scripts (Arabic/Urdu/Hebrew, Hindi, Bengali, etc.) are more sensitive to font size for readability. The UI provides a
font-scalethat auto-adjusts per language, reducing the “you can read it, but it’s uncomfortable” problem (see theme.slint).Finally, to improve CJK rendering on Western-language OS environments, the app selects an appropriate default font per language to avoid poor Chinese/Japanese/Korean rendering (see data.rs).
Engineering Safeguards for Heavy Operations (Move / Clone / Export)
For operations like migrating, cloning, and exporting, the real complexity lies in long chains and uncertainty: is disk space enough? where should temp files go? will operations conflict with each other?
I made two engineering-oriented choices:
These “not-so-visible” strategies determine whether the tool is reliable enough for long-term, high-frequency usage.
Code Structure: Built to Run, Built to Evolve
If you want to get oriented quickly, this is a good starting map:
src/wsl/*wraps, parses, and executeswsl.exeoperations;WslDashboardmanages state and change notifications.src/ui/app.slintis the root UI;src/ui/components/andsrc/ui/views/organize the UI;src/ui/handlers/routes UI events into Rust logic.~/.wsldashboard/settings.tomlandinstances.toml, including migration logic and directory creation.I want it to be a “single portable binary” for users, and a “clear, navigable, extensible” Rust desktop project for contributors.
How I Hope You’ll Use It / Join In
If you’re a heavy WSL user, it turns daily management from “commands + memorization” into “panel + workflow”. If you’re a desktop-app developer, it can also serve as a practical reference project: Slint+Skia UI, Tokio-driven system operations, and an engineering-oriented i18n strategy.
Contributions are very welcome:
If you’d like to make WSL feel more like a modern tool, I think we’re building the same thing.
v0.5.0 feature preview: USB device management (based on usbipd-win to expose Windows-attached USB devices to Linux inside WSL2)
Beta Was this translation helpful? Give feedback.
All reactions