Contributing
VoiceClaw is an open-source project and contributions are welcome. This page covers the development setup, conventions, and workflow.
Development Setup
Section titled “Development Setup”Prerequisites
Section titled “Prerequisites”- Node.js 20+
- Yarn (package manager — always use yarn, not npm)
- Xcode (for iOS builds)
- macOS (required for the desktop Electron app and iOS development)
Install
Section titled “Install”git clone https://github.com/yagudaev/voiceclaw.gitcd voiceclawyarn installThis installs dependencies for all workspaces (mobile, desktop, relay-server, website).
Running Everything
Section titled “Running Everything”# Start relay server + mobile dev server togetheryarn devyarn dev:server # relay server with auto-reloadyarn dev:mobile # Expo dev serveryarn dev:desktop # Electron app in dev modeRelay Server
Section titled “Relay Server”cd relay-servercp .env.example .env # add your GEMINI_API_KEY, OPENAI_API_KEY, RELAY_API_KEYyarn devThe relay server runs on http://localhost:8080. The test page at /test lets you verify WebSocket connectivity from a browser.
Desktop App
Section titled “Desktop App”cd desktopyarn devMobile App
Section titled “Mobile App”cd mobileyarn dev # start Expo dev serveryarn ios # run on iOS simulatoryarn ios:device # run on connected deviceMonorepo Structure
Section titled “Monorepo Structure”voiceclaw/ mobile/ # React Native / Expo iOS app desktop/ # Electron macOS app relay-server/ # TypeScript relay server website/ # Next.js marketing site agent/ # Agent plugins/config (OpenClaw, Hermes, etc.) docs/ # This documentation (GitHub Pages) package.json # Root workspace configThe root package.json defines yarn workspaces. Each sub-package has its own package.json with its own scripts and dependencies.
Branch Strategy
Section titled “Branch Strategy”- Branch naming:
feature/<description>,fix/<description>, etc. - PRs should be reviewed before merging.
Code Style
Section titled “Code Style”No Semicolons
Section titled “No Semicolons”All TypeScript and JavaScript code must omit semicolons:
// Goodconst value = compute()log(`Result: ${value}`)
// Badconst value = compute();log(`Result: ${value}`);File Organization
Section titled “File Organization”Public interface and exports go at the top of each file. Helper functions go at the bottom:
// -- Public interface at the top --
export function buildInstructions(config: SessionConfigEvent): string { const parts: string[] = [] // ... return parts.join("\n\n")}
// -- Helpers at the bottom --
function loadAgentIdentity(provider: string): string { // ...}
function stripMarkdown(text: string): string { // ...}Script Naming
Section titled “Script Naming”Use verb:app naming for scripts (not app:verb):
{ "dev:server": "...", "dev:mobile": "...", "build:web": "..."}General Guidelines
Section titled “General Guidelines”- Use TypeScript for all new code
- Keep functions small and focused
- Use descriptive variable and function names
- Add comments for non-obvious logic, especially protocol translation
- No emoji in code or log messages
Testing
Section titled “Testing”- Relay server: use the test page at
http://localhost:8080/testfor quick WebSocket testing - Mobile: test on a real iOS device or simulator with Expo Go — do not test on web
- Desktop: run
yarn devand verify audio capture, playback, and screen sharing
Making Changes
Section titled “Making Changes”-
Create a feature branch from
mainTerminal window git checkout -b feature/your-feature main -
Make your changes, following the code style guidelines above.
-
Test your changes:
- Run the relay server and verify the protocol works
- Test on the relevant client (mobile device, desktop app)
- Check that existing functionality still works
-
Commit with a clear message describing the change.
-
Push and open a pull request against
main.