Speak into your Android phone and have the text appear on your Linux computer as if typed on the keyboard.
Utter enables voice dictation from an Android device to a Linux computer. The system consists of three components:
- Android App (Kotlin) - Captures voice input via Google speech-to-text
- Relay Server (Node.js/TypeScript) - Routes messages with JWT authentication
- Linux Client (Rust) - Simulates keyboard input on Linux
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ Android │◄───────►│ Relay │◄───────►│ Linux │
│ App │WebSocket│ Server │WebSocket│ Client │
│ │ │ │ │ │
│ Voice Input │ │ Text Relay │ │ Keyboard │
│ Google STT │ │ │ │ Simulation │
└─────────────┘ └──────────────┘ └──────────────┘
cd relay-server
pnpm install
pnpm devServer will start on ws://localhost:8080.
cd utterd
cargo build --release
./target/release/utterdSee android-app/README.md for detailed setup instructions.
- Open Android Studio
- Create new project from the provided files
- Build and install on your device
- Enter relay server URL
- Connect and start dictating
utter/
├── docs/
│ └── PLAN.md # Detailed implementation plan
├── android-app/ # Kotlin Android app
│ ├── MainActivity.kt
│ ├── WebSocketClient.kt
│ ├── activity_main.xml
│ └── README.md
├── relay-server/ # Node.js/TypeScript server
│ ├── src/
│ │ └── index.ts
│ ├── package.json
│ └── README.md
├── utterd/ # Rust client
│ ├── src/
│ ├── Cargo.toml
│ └── README.md
└── README.md # This file
- Node.js 18+
- pnpm - Fast, disk space efficient package manager
Install pnpm:
curl -fsSL https://get.pnpm.io/install.sh | sh -- Rust 1.70+
xdotool(X11) orydotool(Wayland)
Install on Ubuntu/Debian:
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install keyboard tools
sudo apt install xdotool # For X11
# OR
sudo apt install ydotool # For Wayland- Android Studio
- Android device with API 24+ (Android 7.0+)
- Google Keyboard or Gboard
- Start relay server on your Linux computer
- Start Linux client on the same computer
- Find your computer's IP address:
ip addr show | grep "inet " | grep -v 127.0.0.1
- Connect Android app using
ws://YOUR_IP:8080 - Open a text editor on Linux and focus it
- Speak into Android using voice input
- Watch text appear in your Linux editor
Deploy relay server to cloud (Railway, Render, Fly.io) and connect from anywhere.
See docs/PLAN.md for full roadmap.
cd relay-server
pnpm devYou should see:
Utter Relay Server started on port 8080
Phase 1: Direct echo mode - all messages broadcast to all clients
cd utterd
cargo build --release
./target/release/utterdThe client will authenticate with Google OAuth and display real-time message status.
- Start relay server
- Start Linux client
- Connect Android app
- Open a text editor (gedit, VS Code, etc.)
- Focus the editor window
- Speak "Hello world" into Android
- See "Hello world" appear in editor
Port already in use:
# Find process using port 8080
lsof -ti:8080 | xargs kill -9Can't access from Android:
- Check firewall:
sudo ufw allow 8080 - Verify same WiFi network
- Check IP address is correct
xdotool not found:
sudo apt install xdotoolText not appearing:
- Make sure target window is focused
- Try with different applications
- For Wayland, use
--ydotoolflag
Connection refused:
- Verify relay server is running
- Check server URL in command
Connection failed:
- Verify server URL format:
ws://IP:PORT - Check Android and Linux are on same network
- Test server is accessible:
curl http://YOUR_IP:8080
Voice input not working:
- Enable Google Voice Typing in keyboard settings
- Grant microphone permission
- Use Gboard (Google Keyboard)
cd relay-server
pnpm install
pnpm dev # Development with auto-reload
pnpm build # Compile TypeScript
pnpm start # Run production buildcd utterd
cargo build --release
./target/release/utterd --help # See all options
./target/release/utterd --server ws://example.com:8080
./target/release/utterd --tool ydotool # Use ydotool instead of xdotoolSee android-app/README.md for Android Studio setup.
- JWT Authentication - Google OAuth with JWT tokens
- E2E Encryption - Hybrid encryption (X25519 + AES-256-GCM)
- Sender Verification - Cryptographic proof of message authenticity
- User Isolation - Messages only route between your devices
See docs/ for detailed architecture documentation.
Architecture inspired by happy-server, which demonstrates WebSocket relay with end-to-end encryption.
This is currently a personal MVP. Contributions welcome after Phase 1 is stable.
MIT
Status: Production-ready with JWT authentication and E2E encryption