Thanks for taking the time to contribute.
- For bugs and small fixes, open a pull request directly.
- For new commands, protocol changes, or anything that widens what a remote client can do, open an issue first so we can discuss the security implications.
- Do not open a public issue for a security vulnerability. See SECURITY.md.
Requires Go (version pinned in go.mod) and a working CGO toolchain — Fyne and
the platform helpers are CGO-based, so CGO_ENABLED=1 is mandatory.
# macOS: Xcode command line tools
xcode-select --install
# Debian/Ubuntu (for the linux toolchain / cross builds)
sudo apt-get install build-essential libgl1-mesa-dev xorg-dev
Then:
go mod download
./tools/dev.sh # regenerates version.go, then runs the app
version.go is generated by the build tooling and is gitignored — do not commit
or hand-edit it. version.json is the source of truth for the version number.
gofmt -l . # must print nothing
go vet ./...
go build ./...
There is no test suite yet. If you are adding logic that can be tested without a display or input injection, please add tests — they are welcome.
- Standard
gofmt. No custom linters are enforced in CI beyondgofmtandgo vet. - Match the surrounding code: the project is deliberately a small number of
files, with
main.goholding application logic and thin*_darwin.go/*_windows.go/*_other.gofiles for platform specifics. - Comment why, not what. Several existing comments explain non-obvious platform workarounds (robotgo SIGTRAP on macOS, NX media key events, Fyne activation policy) — keep that standard.
Anything touching these areas gets extra scrutiny; please explain the reasoning in the PR description:
- The command dispatch in
handleCommand - Authentication, the rate limiter, or password handling
AllowedCommands/ key access control enforcement- Input that reaches
exec.Command,osascript, or a shell - The macOS entitlements in
tools/extras/osx-entitlements.plist
New commands must be added to defaultCommands so they are individually
toggleable, and must call auditLog with enough detail to reconstruct what
happened.
build.yaml runs on every push, including on forks, and produces working
unsigned macOS and Windows builds on GitHub-hosted runners. Code signing and
publishing are opportunistic: they only happen when the Bitfocus signing
credentials are present and github.repository_owner == 'bitfocus', so nothing
in the workflow fails on a fork. lint.yaml (gofmt + go vet) is what gates
pull requests.
Stable releases are cut by pushing a v* tag that matches version.json;
tools/check-tag-version.sh enforces the match.
By contributing you agree that your contributions are licensed under the MIT License, as set out in LICENSE.