Contributing to DSH Studio
August 21, 2026 · View on GitHub
Thanks for looking. This is a small project with a small number of firm opinions, and this file is where they are written down so a pull request does not have to discover them in review.
Getting set up
You need Node.js 22.19+, pnpm 10, and a stable Rust toolchain. On Windows that also means the MSVC build tools; on Linux, the WebKitGTK development packages:
sudo apt-get install libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev
Then:
pnpm install
pnpm tauri dev
The first Rust build takes a few minutes. After that it is incremental. Front end changes hot-reload; Rust changes rebuild and relaunch the window.
pnpm devon its own starts only Vite. The page it opens in a browser has no Tauri APIs, so the UI will fail immediately. Always usepnpm tauri dev.
The dev server binds port 1420 and will not fall back to another one, because
devUrl in src-tauri/tauri.conf.json is a fixed URL that the Rust side cannot
follow. If the port is taken, find out by what — it is often another Tauri
project, since 1420 is the template default.
Before you open a pull request
Run all four. CI runs the same set on Linux, Windows and macOS, and a red CI is the only thing that will hold a review up mechanically:
pnpm lint # ESLint, zero warnings
pnpm exec tsc --noEmit # strict TypeScript
pnpm test # store and i18n behaviour
cargo test --manifest-path src-tauri/Cargo.toml --workspace
Formatting is not negotiable but it is also not your problem — run
pnpm format and cargo fmt --all and move on.
House rules
Comments explain why, not what. A comment that restates the line below it is noise that will go stale. A comment that records the reason a thing is unusual is the most valuable text in the file. If a line looks wrong and is not, say why it isn't.
No suppression in place of a fix. No @ts-ignore, no as any, no
.skipped test, no empty catch, no sleeping until a race stops reproducing.
If something needs suppressing, the reason belongs in the pull request, not
hidden in the diff.
Both languages, always. src/lib/i18n.ts derives the type of the Chinese
dictionary from the English one, so a missing translation is a build error
rather than a blank label someone finds later. Add both.
Loopback is not a setting. The service binds 127.0.0.1 and takes its port
from the kernel. Neither is configurable, and a pull request making either one
configurable needs to argue the security case first: the harness can run shell
commands.
Don't fork upstream into this repo. Nothing from the harness is vendored or patched here — that is the whole architectural bet. Extensions to the harness UI should go through its own client-plugin system.
Commit messages
Commits here are 类型: 简短描述 — a type, a colon, and a short description in
Chinese:
功能: 托盘常驻、关闭到托盘与全新应用图标
修复: Node 版本目录解析出同一版本时按路径定序
重构: 界面改为桌面软件形态,端口读数移入底部状态栏
构建: 补上缺失的 Prettier 配置并统一格式
Types in use: 功能 修复 重构 构建 测试 文档 ci.
If Chinese is not a language you write, English is fine — a clear message in a
language you actually speak beats a mechanical translation. Use the same shape:
fix: , feat: , and so on.
The body is for the reasoning. What changed is visible in the diff; why it changed is not.
Where things live
src/ React 19 + Tailwind 4 shell UI
src-tauri/src/harness/ supervisor, readiness parsing, health probe, install
src-tauri/src/tray.rs tray icon and its menu
src-tauri/crates/
node-runtime/ find a usable Node on this machine
proc-guard/ kill a process tree and mean it
node-runtime and proc-guard know nothing about Tauri or about this app, and
should stay that way. If a change to either one needs to reach for something
app-specific, that is a sign the change belongs above them instead.
Reporting bugs
Please include your OS and version, how you installed Node, and whether the service was running at the time. If the shell logged anything, the output pane is selectable — copy it in.
Anything that leaves a process behind after the window closes is worth a report on its own, with as much detail as you can get about what was running.
For anything with security implications, see SECURITY.md rather than opening a public issue.
License
By contributing you agree that your contributions are licensed under the MIT License, the same as the rest of the project.