CodeVetter · Repo Unpack · Contributor handoff
rustdesk/rustdesk
Read AGENTS.md first — it is the authoritative style/scope contract (no unwrap, no nested tokio runtimes, minimal diffs, additive-only changes, import/comment/localization rules). Build requires the hbb_common submodule and system deps (vcpkg/pkg-config for vpx/opus/aom); the pinned Rust 1.75 toolchain and Flutter 3.24.5 matter. Safe edit boundaries: new code in feature modules or src/platform/*; dangerous: shared protocol/session files and anything touching pre-auth limits.
- AGENTS.md is the governing doc (CLAUDE.md just @-imports it): bans unwrap/expect outside tests & lock acquisition, bans nested runtimes/block_on in async, bans locks across .await, mandates single-braced use blocks per crate, and requires a 'regression-surface' report for every change.
- First files to read for any session work: src/core_main.rs (entry/CLI), src/server.rs + src/server/connection.rs (host), src/client.rs + src/client/io_loop.rs (controller), src/ipc.rs (inter-process Data enum), libs/base/src/config/keys.rs (all option names).
- Toolchain pins: rust-version 1.75 (Cargo.toml), CI RUST_VERSION 1.75 / macOS 1.81, Flutter 3.24.5 (3.44.9 win-arm64), flutter_rust_bridge '=1.80'/1.80.1 — mismatched frb versions regenerate incompatible bindings.
- Build commands: `cargo build --locked --features flutter` (desktop lib) or `python3 build.py` for full app packaging; quick checks: `cargo test --locked --lib --features drm` (Linux), `flutter test` in flutter/; vcpkg must provide libvpx/libyuv/opus/aom per Dockerfile.
- Editing `libs/hbb_common` costs a round-trip: it is shared with rustdesk-server — put client-only code in libs/base instead; base::config::keys re-exports the hbb_common keys so callers never import from two places.
- Known traps: `is_quick_support_exe` must stay in sync with libs/portable/src/main.rs; the CLI↔IPC routing list is_user_main_ipc_scope_cli_command has a regression test; IPC FileBlockFromCM requires message-then-send_raw ordering; tray icon assets are include_bytes!()'d from res/ (compile-time).
- Process model trap: the same binary runs as service/root (--server), user GUI, tray, and --cm simultaneously; shared state does NOT cross processes — it goes through ipc::Data or Config file sync (sync_and_watch_config_dir); never assume a global static is visible to the other process.
- Security-sensitive zones to touch carefully: pre-auth limits in connection.rs/rendezvous_mediator.rs (64/16/128KiB/180s/32-punch/16-answerer constants), ipc/auth.rs peer verification, updater.rs update paths, custom_server.rs signature verification — changes here need the 'regression surface' analysis AGENTS.md demands.
- Flutter-side session ownership: Session<T:InvokeUiSession> + LoginConfigHandler (ui_session_interface.rs) is the shared abstraction — Flutter implements it via FlutterHandler/event streams, legacy Sciter via remote::SciterHandler; new UI behavior should be added to the InvokeUiSession trait rather than bypassing it.
- cfg discipline: almost every module is gated per-OS/feature; `#[cfg(not(any(target_os="android",target_os="ios")))]` is the desktop idiom, `feature="flutter"` selects the UI backend, and imports must be folded into per-crate braced blocks with separate use only for differently-gated items.
- Testing expectation: add #[cfg(test)] mods or files next to the code (video_qos/tests pattern); CI only runs named filters on Linux and one flutter test file — a renamed test silently stops running because empty filters exit 0 (noted in workflow comments).