Contributions are welcome by pull request. This is a Win32 FFI codebase, so the conventions below are about keeping it reviewable rather than about ceremony.
Build from source
Requires Rust (stable) and the MSVC toolchain on Windows.
.\build.ps1 -Mode prod
Output: target\release\wiradesk.exe and
target\release\wiradesk-settings.exe.
Running the tests
The suite needs one environment variable. The daemon links an elevation manifest, which would otherwise apply to the test harness too and make it fail before any test ran:
$env:WIRADESK_SKIP_MANIFEST = '1' cargo test --workspace
What to run before submitting
cargo fmt --all cargo clippy --workspace --all-targets -- -D warnings cargo test --workspace
The four gates CI enforces
| Gate | What it does |
|---|---|
| Build | fmt, clippy -D warnings, tests, and a release build, on Windows. |
| Secret scan | gitleaks over both history and the working tree, using .gitleaks.toml. |
| Dependencies | cargo-deny check over advisories, licenses, bans and sources, with the graph pinned to x86_64-pc-windows-msvc. |
| License | Part of the same cargo-deny run: a new dependency carrying a license outside the allow-list fails the build, deliberately. |
gitleaks allowlist to make a finding go away. Triage it.Unsafe code
This is a Win32 FFI codebase, so unsafe is unavoidable. Undocumented
unsafe is not. undocumented_unsafe_blocks and
missing_safety_doc are deny in the workspace lints, so every
unsafe block needs a SAFETY: comment and the build fails without one.
Write the precondition the block actually relies on, not a description of the call. The useful ones usually name one of these:
- a buffer capacity, against the size argument passed to Win32;
- which component owns a handle, and where it is released exactly once;
- which thread the call must run on;
- why an invalid handle is tolerable, because the API reports failure rather than faulting.
The daemon runs elevated with a global keyboard hook. That is why this boundary, and not some other, is the one held to a standard.
Conventions worth knowing
CLAUDE.md,AGENTS.md, and.cursorruleshold the instructions AI coding tools read, and they are kept in sync. Change one and change all three in the same commit; drift between them is silent, and the tool reading the stale copy is the one that misbehaves.CHANGELOG.mdis not free-form.release.ymlextracts the## [x.y.z]section matching the git tag and publishes it as the release notes, and the in-app updater shows that same section to whoever is deciding whether to update. A tag with no matching section fails the release rather than shipping notes nobody wrote.- Who may move which version digit is a rule, not a convention. Work needing a minor or major bump belongs under Unreleased until the owner decides.
Reporting something
A bug or an idea
Open an issue on the repository. Useful: your Windows build, the Wira Desk version, what you did, what happened, and what you expected instead.
A vulnerability
Not an issue. Use GitHub Security Advisories so the report stays private until a fix exists. There is no bounty and no guaranteed response time.
Writing a changelog entry
Write it for the person deciding whether to update, not for the commit log. The in-app updater shows that text verbatim; it is the last thing someone reads before they let an elevated installer run.