Contributing
Thanks for your interest. Bug reports with rdc doctor output, platform test reports, and small
focused pull requests are all welcome.
Before you start
-
Read AGENTS.md: the design and security principles changes are reviewed against.
-
For anything beyond a small fix, open an issue first so we can agree on the approach. The architecture doc explains how the pieces fit.
-
Security problems: do not open a public issue. See SECURITY.md.
-
Platform reports are contributions too. If you run rdc on a platform marked untested in the README, tell us what happened, good or bad.
Development setup
git clone https://github.com/bscott/rdc && cd rdc
cargo build --release
cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --all
Build dependencies per OS are in docs/install.md. CI runs the same four commands on Linux, macOS and Windows with warnings as errors, so run them before pushing.
Trying changes locally without a second machine
./target/release/rdc serve --dev-loopback # unauthenticated 127.0.0.1, testing only
./target/release/rdc -t http://127.0.0.1:7770 shot
./target/release/rdc -t http://127.0.0.1:7770 click 400 300
Or skip the daemon entirely with --target local, which exercises the same Desktop
implementation in-process.
Trying the MCP server
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | ./target/release/rdc mcp -t local
Repository layout
| Path | Contents |
|---|---|
src/proto.rs | wire and domain types shared by daemon, client, CLI and MCP |
src/desktop/mod.rs | the Desktop trait |
src/desktop/local/ | in-process implementation: capture, input worker, per-platform window code |
src/desktop/remote.rs | HTTP client implementation |
src/server/ | axum daemon, whois auth middleware, routes |
src/tailscale.rs | LocalAPI discovery per platform, CLI fallback |
src/mcp.rs, src/view.rs | MCP tools and pixel↔point mapping |
src/keys.rs | key chord grammar |
src/service/ | LaunchAgent and systemd installers |
src/doctor.rs, src/permissions.rs | readiness checks and macOS TCC helpers |
scripts/macos/ | signing identity and .app bundling |
skills/rdc/ | the agent skill |
docs/ | user documentation |
How changes reach a release
- Every release has a branch named
release/<version>(for examplerelease/0.4.0). Open your pull request against the current release branch, notmain. - CI runs on the pull request: rustfmt, clippy with warnings as errors, and the tests, on Linux, macOS and Windows. All three must pass. First-time contributors’ runs wait for a maintainer to approve them.
- A maintainer reviews and merges into the release branch. The release branch is then tested on real machines.
- When the release is ready, a pull request from the release branch to
mainis reviewed and approved by a person, merged, and tagged.mainonly ever contains released code; it is protected and cannot be pushed to directly.
Tests are required
Pull requests are expected to come with tests, and reviewers will ask for them. The bar:
- New logic gets unit tests. Parsers, mapping functions, policy decisions, anything with
branches. Put them in a
#[cfg(test)] mod testsnext to the code. - Every bug fix gets a regression test that fails without the fix.
- Server behaviour gets a router test.
src/server/tests.rsdrives the real axum router with a fakeDesktopand a fake identity source; add a case there when you touch authentication, capabilities, routes or the audit log. - Platform code states what was run. Code behind
cfg(target_os)cannot be tested in CI beyond compiling, so the PR description must say which OS you ran it on and what you did. - Tests must be deterministic, must not need a network or a real display, and must clean up files they create.
Pull request checklist
-
The PR targets the current
release/<version>branch. -
Tests are included (see above).
-
cargo fmt,cargo clippy --all-targets -- -D warningsandcargo testpass locally. -
Say which platforms you actually ran on, and how (foreground, service, MCP).
-
If behaviour changed, update the relevant page in
docs/and, if it affects agents,skills/rdc/SKILL.md. -
Add a line under Unreleased in
CHANGELOG.md; it becomes the release notes. -
If you verified a platform that the README marks untested, update the status table.
-
Commits are descriptive; one logical change per commit where practical.
Style
- Keep the
Desktoptrait the single seam: new capabilities go there first, then to the wire API, then to the CLI and MCP. All three surfaces must stay equivalent. - No new network listeners, no shell execution, no credentials in the tree.
- Prefer returning
RdcErrorover panicking in daemon paths. - Platform-specific code goes behind
cfg(target_os = …)in its own module; keep the common path compiling on all three OSes. From Linux, afterrustup target add x86_64-pc-windows-gnu aarch64-apple-darwin, runcargo clippy --target <triple> --all-targets -- -D warningsfor both; CI runs clippy with warnings as errors on every platform, and a lint that only fires on one of them will fail the build there.
Releasing (maintainers)
- On the release branch, move the Unreleased entries in
CHANGELOG.mdunder a new## <version> — <date>heading and bumpversioninCargo.toml. - Test the release branch on the real machines:
rdc doctor, screenshot, input, focus, and the MCP tools from Claude Code. - Open a pull request from
release/<version>tomain. A person reviews and approves it, and CI must be green. - Merge, then from
main:git tag -a v<version> -m "rdc <version>" && git push origin v<version>. The release job builds all platforms and turns the changelog section into the release notes. - Create the next
release/<version>branch frommain.
License and sign-off
rdc is licensed under the GPL-3.0-or-later. By contributing you agree that your contributions are licensed under the same terms.
Please sign off each commit (git commit -s), which adds a Signed-off-by: line certifying
the Developer Certificate of Origin: that you wrote the
change or otherwise have the right to submit it under the project license.