Contributing¶
Thanks for considering contributing to VoiceLayer! This guide covers development setup, testing, and the PR process.
Development Setup¶
# Clone the repo
git clone https://github.com/EtanHey/voicelayer.git
cd voicelayer
# Install dependencies
bun install
# Install audio prerequisites (macOS)
brew install sox whisper-cpp
pip3 install edge-tts
# Download a whisper model for STT tests
mkdir -p ~/.cache/whisper
curl -L -o ~/.cache/whisper/ggml-base.en.bin \
https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en.bin
Project Structure¶
voicelayer/
├── src/
│ ├── mcp-server.ts # MCP server entry point
│ ├── tts.ts # Text-to-speech (edge-tts)
│ ├── input.ts # Mic recording (sox)
│ ├── stt.ts # STT backends (whisper.cpp + Wispr)
│ ├── audio-utils.ts # Shared audio utilities
│ ├── paths.ts # /tmp path constants
│ ├── session-booking.ts # Lockfile-based session mutex
│ ├── session.ts # Session lifecycle
│ ├── report.ts # QA report renderer
│ ├── brief.ts # Discovery brief renderer
│ ├── schemas/ # QA + discovery category schemas
│ └── __tests__/ # Test files
├── scripts/
│ ├── speak.sh # Standalone TTS command
│ └── test-wispr-ws.ts # Wispr Flow WebSocket test
├── docs/ # MkDocs documentation (this site)
├── package.json
├── tsconfig.json
├── mkdocs.yml
└── README.md
Running Tests¶
# Run all tests
bun test
# Run a specific test file
bun test src/__tests__/tts.test.ts
# Run tests matching a pattern
bun test --grep "session booking"
The test suite covers 75 tests with 178 assertions across:
- TTS synthesis and playback
- STT backend detection and transcription
- Session booking (lock/release/stale cleanup)
- Input recording and silence detection
- QA report and discovery brief rendering
- MCP server tool routing
Most tests mock external tools (sox, edge-tts, whisper-cpp) so they run without audio hardware.
Code Style¶
- TypeScript with strict mode
- Bun runtime (not Node.js)
- No formatting tools — keep consistent with existing code
- JSDoc comments on exported functions
- Module header comments describing purpose and dependencies
Making Changes¶
Branch from main¶
Commit Messages¶
Follow conventional commits:
feat: add new voice mode
fix: handle edge-tts timeout
docs: update STT backend comparison
test: add session booking race condition test
chore: update dependencies
Submit a PR¶
- Push your branch:
git push -u origin feature/your-feature - Create a PR against
main - CodeRabbit will auto-review within 1-2 minutes
- Address any HIGH severity findings
- Merge when clean
Architecture Principles¶
- Delegate audio I/O — use system tools (sox, edge-tts, whisper-cpp), don't bundle audio libraries
- File-based IPC — lockfiles and touch-files for cross-process communication
- Fail gracefully — never throw from MCP tool handlers, always return structured errors
- Local-first — prefer local processing (whisper.cpp) over cloud services
- Zero config — sensible defaults, auto-detection for models and backends
Adding a New Voice Mode¶
- Define the tool in
mcp-server.ts(ListToolsRequestSchema handler) - Add a handler function (
handleYourMode) - Route it in the CallToolRequestSchema switch
- Add tests in
src/__tests__/ - Document in
docs/modes/your-mode.md - Add to the nav in
mkdocs.yml
Adding a New STT Backend¶
- Implement the
STTBackendinterface instt.ts: - Add detection logic in
getBackend() - Add tests for availability detection and transcription
- Document in
docs/architecture/stt-backends.md