diff --git a/CLAUDE.md b/CLAUDE.md index 14e54a3..2620656 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -20,4 +20,4 @@ curl -fsSL https://raw.githubusercontent.com/eladcandroid/claude-code-voice/main ## Supported languages -en, he, es, fr, de, ja, ko, pt, it, ru, zh, ar, hi, tr, nl, pl, uk, el, cs, da, sv, no — and any other language Apple's SFSpeechRecognizer supports. +en, he, es, fr, de, ja, ko, pt, it, ru, zh, zh-hk, ar, hi, tr, nl, pl, uk, el, cs, da, sv, no — and any other language Apple's SFSpeechRecognizer supports. diff --git a/README.md b/README.md index d430585..247dfcf 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ # Claude Code Voice (macOS) -Adds native on-device speech-to-text to Claude Code's `/voice` command using Apple's `SFSpeechRecognizer`. Natively supported languages proxy to Anthropic's server; unsupported languages (Hebrew, Arabic, etc.) transcribe locally via Apple STT. No API keys, no binary patching — survives Claude Code updates. +Adds native speech-to-text to Claude Code's `/voice` command using Apple's `SFSpeechRecognizer`. Claude-native languages are proxied to Anthropic's voice server, while unsupported languages (Hebrew, Arabic, etc.) are transcribed locally with Apple STT. No API keys, no binary patching — survives Claude Code updates. ## Quick install ```bash -curl -fsSL https://raw.githubusercontent.com/eladcandroid/claude-code-voice/main/setup.sh | bash +curl -fsSL https://raw.githubusercontent.com/dr-data/claude-code-voice/main/setup.sh | bash ``` ## Requirements @@ -65,10 +65,27 @@ Type `/config` in Claude Code to change the language. The voice server picks it | Norwegian | `no` | Anthropic | | **Hebrew** | `he` | Apple STT | | **Arabic** | `ar` | Apple STT | -| **Chinese** | `zh` | Apple STT | +| **Chinese (Mandarin)** | `zh` | Apple STT | +| **Cantonese (Hong Kong)** | `yue` or `zh-hk` | Apple STT | Any language supported by Apple's `SFSpeechRecognizer` works — the 20 natively supported languages are proxied to Anthropic's server for best quality. +### Cantonese setup + +1. In Claude Code, run `/config` and set the language to `yue` (or `zh-hk`, `cantonese`, `廣東話`, `粵語` — all work). +2. Download the Cantonese speech model on macOS so Apple STT can work offline: + - **System Settings → Keyboard → Dictation** + - Enable **Dictation**, then open the **Language** dropdown + - Click **Add Language…** and select **Chinese (Cantonese)** + - macOS will download the on-device model (~100–200 MB) +3. Once downloaded, restart Claude Code and hold **Space** to speak in Cantonese — transcription runs fully on-device. + +## Token usage and local processing + +- **Claude-native languages** (shown as `Anthropic` in the table): audio is proxied to Anthropic for transcription, so this path uses Claude's voice backend and may consume tokens/usage. +- **Apple STT languages** (shown as `Apple STT`): transcription is done on your Mac with `SFSpeechRecognizer`, so speech-to-text itself is local. +- In both cases, once text is inserted into Claude Code, your normal chat usage still applies. + ## How it works Claude Code has an undocumented `VOICE_STREAM_BASE_URL` env var that redirects its voice WebSocket. This project runs a native macOS app on `localhost:19876` that acts as a smart router: @@ -76,13 +93,18 @@ Claude Code has an undocumented `VOICE_STREAM_BASE_URL` env var that redirects i - **Native languages** (20) → proxied to Anthropic's voice server with OAuth token from Keychain - **Other languages** → transcribed locally via Apple's on-device `SFSpeechRecognizer` -``` - ┌─ native lang ──▶ Anthropic server -┌─────────────┐ audio │ (streaming STT) -│ Claude Code │──chunks──▶│ voice-server -│ /voice + ␣ │◀──text───│ -└─────────────┘ └─ other lang ──▶ Apple STT - (on-device) +```text +┌──────────────┐ audio chunks ┌──────────────┐ +│ Claude Code │ ────────────────────▶ │ voice-server │ +│ /voice + ␣ │ ◀──────────────────── │ (local) │ +└──────────────┘ transcript └──────┬───────┘ + │ + ┌─────────────┴─────────────┐ + │ │ + native Claude language other language + │ │ + ▼ ▼ + Anthropic voice STT Apple on-device STT ``` Everything is a single Swift binary — WebSocket server, proxy, and speech recognition combined. No external runtimes needed. @@ -90,7 +112,7 @@ Everything is a single Swift binary — WebSocket server, proxy, and speech reco ## Uninstall ```bash -curl -fsSL https://raw.githubusercontent.com/eladcandroid/claude-code-voice/main/uninstall.sh | bash +curl -fsSL https://raw.githubusercontent.com/dr-data/claude-code-voice/main/uninstall.sh | bash ``` ## Project structure diff --git a/scripts/server.swift b/scripts/server.swift index 95a777c..7af131a 100644 --- a/scripts/server.swift +++ b/scripts/server.swift @@ -25,6 +25,8 @@ let localeMap: [String: String] = [ "it": "it-IT", "italian": "it-IT", "italiano": "it-IT", "ru": "ru-RU", "russian": "ru-RU", "русский": "ru-RU", "zh": "zh-CN", "chinese": "zh-CN", + "yue": "zh-HK", "cantonese": "zh-HK", "廣東話": "zh-HK", "广东话": "zh-HK", "粵語": "zh-HK", + "zh-hk": "zh-HK", "ar": "ar-SA", "arabic": "ar-SA", "hi": "hi-IN", "hindi": "hi-IN", "id": "id-ID", "indonesian": "id-ID", diff --git a/setup.sh b/setup.sh index bd71f83..c9eb7e3 100755 --- a/setup.sh +++ b/setup.sh @@ -10,11 +10,16 @@ INSTALL_DIR="$HOME/.local/share/claude-code-voice" if [ ! -f "scripts/server.swift" ]; then echo "Downloading claude-code-voice..." rm -rf "$INSTALL_DIR" - git clone --depth 1 https://github.com/eladcandroid/claude-code-voice.git "$INSTALL_DIR" 2>/dev/null + git clone --depth 1 https://github.com/dr-data/claude-code-voice.git "$INSTALL_DIR" 2>/dev/null cd "$INSTALL_DIR" fi SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +# Detect GitHub username from this repo's git remote so forked copies display correct URLs +_REMOTE_URL=$(git -C "$SCRIPT_DIR" remote get-url origin 2>/dev/null || echo "") +_GITHUB_USER=$(echo "$_REMOTE_URL" | sed -E 's|.*github\.com[:/]([^/]+)/.*|\1|') +_GITHUB_USER="${_GITHUB_USER:-dr-data}" SCRIPTS="$SCRIPT_DIR/scripts" APP="$SCRIPTS/VoiceServer.app" @@ -116,5 +121,8 @@ echo "" echo "=== Done ===" echo "Restart Claude Code, enable /voice, and speak." echo "Switch language with /config." +echo "Supported /config language codes:" +echo " en, es, fr, de, ja, ko, pt, it, ru, hi, id, pl, tr, nl, uk, el, cs, da, sv, no, he, ar, zh, zh-hk" +echo " plus any language supported by Apple SFSpeechRecognizer" echo "" -echo "Uninstall: curl -fsSL https://raw.githubusercontent.com/eladcandroid/claude-code-voice/main/uninstall.sh | bash" +echo "Uninstall: curl -fsSL https://raw.githubusercontent.com/$_GITHUB_USER/claude-code-voice/main/uninstall.sh | bash" diff --git a/uninstall.sh b/uninstall.sh index 5a6422a..ae085e1 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -4,6 +4,12 @@ set -euo pipefail echo "=== Uninstalling Claude Code Voice ===" echo "" +# Detect GitHub username from the installed repo before we remove it +_INSTALL_DIR="$HOME/.local/share/claude-code-voice" +_REMOTE_URL=$(git -C "$_INSTALL_DIR" remote get-url origin 2>/dev/null || echo "") +_GITHUB_USER=$(echo "$_REMOTE_URL" | sed -E 's|.*github\.com[:/]([^/]+)/.*|\1|') +_GITHUB_USER="${_GITHUB_USER:-dr-data}" + # 1. Stop and remove launch agents (current + legacy names) for name in com.claude-code-voice com.claude-code-voice.server com.hebrew-voice.server; do PLIST="$HOME/Library/LaunchAgents/$name.plist" @@ -52,3 +58,4 @@ done echo "" echo "=== Uninstall complete ===" echo "Restart Claude Code for changes to take effect." +echo "Reinstall: curl -fsSL https://raw.githubusercontent.com/$_GITHUB_USER/claude-code-voice/main/setup.sh | bash"