Thank you for your interest in contributing to OpenGUI!
- Fork the repository
- Clone your fork and create a new branch
- Follow the setup instructions in README.md
cd server
./start.sh- Code style is enforced by Biome — run
pnpm format-and-lint:fixbefore committing - Tests:
pnpm test
cd client
./gradlew assembleDebugA phone action crosses the model prompt, server execution pipeline, WebSocket payload, and Android accessibility implementation. Keep the action name and payload fields aligned across every layer.
The existing long_press(point='<point>x y</point>') action is a useful reference:
server/apps/backend/src/modules/graph-agent/graph/nodes/executor/entry.node.tsexposes the action to the model in the GUI action space.server/apps/backend/src/modules/graph-agent/graph/nodes/executor/parse-action.node.tsparses the model output and normalizespointtostart_coords. Its behavior is covered byparse-action.node.spec.ts.server/apps/backend/src/modules/graph-agent/graph/nodes/executor/execute-action.node.tsallows the action, convertsstart_coordsto the wire fieldsstart_xandstart_y, and sends the request to the selected execution socket.client/core_common_jvm/src/main/java/com/coremate/opengui/common_jvm/dto/ActionDtos.ktdeserializes those fields into the AndroidActionInputsmodel.client/core_accessibility/src/main/java/com/coremate/opengui/accessibility/ActionExecutor.ktvalidates the inputs and dispatches the action.client/core_accessibility/src/main/java/com/coremate/opengui/accessibility/actions/LongPressAction.ktcalls the low-level implementation inGestureService.kt.
Follow the same path when adding a new action.
- Define the model contract. Add the action name, parameters, and usage guidance to the action space in
entry.node.ts. - Parse and validate the output. Add a focused case to
parse-action.node.spec.ts. Changeparse-action.node.tsonly when the new action needs syntax or coordinate normalization that the generic parser does not already support. - Update the server action contract. Add the action to
MobileActionTypeinexecute-action.node.ts. If it introduces new inputs, add them toActionInputsinstate.types.tsand map them inbuildActionParams(). - Keep the wire payload aligned. New fields emitted by
buildActionParams()must have matching@SerializedNamefields in the AndroidActionInputsdata class inActionDtos.kt. - Implement Android dispatch. Add input validation and a dispatch branch in
ActionExecutor.kt, then add a focused action class undercore_accessibility/.../actions/. - Add a low-level primitive only when needed. Reuse existing
GestureServicemethods when possible. ExtendGestureService.ktonly if the action requires behavior that existing click, long-press, swipe, text, or global navigation primitives cannot provide. - Review loop semantics. If the new action is passive or should be treated specially by repetition detection, update
post-execute.node.tsand its tests.
Use the same action name at every layer. Keep parser coordinates as start_coords / end_coords, wire coordinates as start_x / start_y / end_x / end_y, and explicitly serialize any additional fields shared with Android.
Run the focused parser tests and server checks:
cd server
pnpm --filter backend test -- parse-action.node.spec.ts --runInBand
pnpm build
pnpm format-and-lintRun the Android unit tests and build the APK:
cd client
./gradlew :core_accessibility:testDebugUnitTest :app:assembleDebugFor a new or changed gesture, also test on a real Android device. Start a task that makes the model select the action, confirm that the server sends the expected payload, verify the gesture on the target screen, and confirm that execution continues with a fresh screenshot. Add an instrumented test when the behavior depends on Android framework APIs that cannot be covered by a local unit test.
- Keep PRs focused — one feature or fix per PR
- Include a clear description of the change and why it's needed
- Add tests for new functionality when possible
- Ensure
pnpm format-and-lintpasses (server)
graph-agent/is the AI orchestration core — changes here require extra care and thorough testingcredits/,tos/,knowledge/are intentionally stubbed modules — do not delete them, only modify the stub behavior- See CLAUDE.md for detailed architecture context
- Use GitHub Issues for bug reports and feature requests
- See the public label policy for how maintainers classify issues and pull requests
- For security vulnerabilities, see SECURITY.md
By contributing, you agree that your contributions will be licensed under the Business Source License 1.1 (BUSL-1.1), unless a separate written agreement says otherwise.
You also grant Core-Mate the right to use, modify, distribute, sublicense, commercially license, and relicense your contributions as part of OpenGUI. For substantial external contributions, maintainers should request a Contributor License Agreement before accepting the change.