@domdhi/claude-code-tts 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@
3
3
  claude-code-tts — TTS daemon
4
4
  Persistent background process. Keeps model loaded. Serves speech via TCP.
5
5
 
6
- Protocol (JSON lines over localhost:6254):
6
+ Protocol (JSON lines over localhost — port derived from install dir):
7
7
  {"cmd": "speak", "text": "...", "voice": "af_heart", "speed": 1.0, "project": "repo-name"}
8
8
  {"cmd": "stop"}
9
9
  {"cmd": "ping"}
@@ -30,8 +30,12 @@ os.environ.setdefault('OMP_NUM_THREADS', '6')
30
30
  os.environ.setdefault('ONNXRUNTIME_NUM_THREADS', '6')
31
31
 
32
32
  HOST = '127.0.0.1'
33
- PORT = 6254
34
33
  DAEMON_DIR = os.path.dirname(os.path.abspath(__file__))
34
+
35
+ # Port is derived from install location — each install gets its own daemon port,
36
+ # so multiple projects with local installs don't collide.
37
+ import hashlib as _hashlib
38
+ PORT = 49152 + (int(_hashlib.md5(DAEMON_DIR.encode()).hexdigest(), 16) % 16384)
35
39
  PID_FILE = os.path.join(DAEMON_DIR, 'daemon.pid')
36
40
  MODEL_PATH = os.path.join(DAEMON_DIR, 'models', 'kokoro-v1.0.onnx')
37
41
  VOICES_PATH = os.path.join(DAEMON_DIR, 'models', 'voices-v1.0.bin')
@@ -20,7 +20,8 @@ VOICES_FILE = os.path.join(HOOK_DIR, 'voices.json')
20
20
  DAEMON_SCRIPT = os.path.join(HOOK_DIR, 'daemon.py')
21
21
 
22
22
  DAEMON_HOST = '127.0.0.1'
23
- DAEMON_PORT = 6254
23
+ import hashlib as _hashlib
24
+ DAEMON_PORT = 49152 + (int(_hashlib.md5(HOOK_DIR.encode()).hexdigest(), 16) % 16384)
24
25
 
25
26
 
26
27
  def _start_daemon():
@@ -21,7 +21,8 @@ VOICES_FILE = os.path.join(HOOK_DIR, 'voices.json')
21
21
  DAEMON_SCRIPT = os.path.join(HOOK_DIR, 'daemon.py')
22
22
 
23
23
  DAEMON_HOST = '127.0.0.1'
24
- DAEMON_PORT = 6254
24
+ import hashlib as _hashlib
25
+ DAEMON_PORT = 49152 + (int(_hashlib.md5(HOOK_DIR.encode()).hexdigest(), 16) % 16384)
25
26
 
26
27
  READ_ALL_CHAIN = False # True = speak all assistant messages in chain, False = last only
27
28
 
@@ -19,7 +19,8 @@ VOICES_FILE = os.path.join(HOOK_DIR, 'voices.json')
19
19
  DAEMON_SCRIPT = os.path.join(HOOK_DIR, 'daemon.py')
20
20
 
21
21
  DAEMON_HOST = '127.0.0.1'
22
- DAEMON_PORT = 6254
22
+ import hashlib as _hashlib
23
+ DAEMON_PORT = 49152 + (int(_hashlib.md5(HOOK_DIR.encode()).hexdigest(), 16) % 16384)
23
24
 
24
25
 
25
26
  def strip_markdown(text):
package/INSTALL.md CHANGED
@@ -43,7 +43,7 @@ The installer automatically:
43
43
  7. Patches `settings.json` / `settings.local.json` with hook entries (backs up original first)
44
44
 
45
45
  **Local vs global:**
46
- - Default (no flag): everything goes into `./.claude/` — hook scripts, commands, and `settings.local.json` (gitignored). Good for shipping TTS config alongside a project. Note: the local daemon runs on `localhost:6254`; if you have two local-installed projects open at once, they'll share the port (the first one wins).
46
+ - Default (no flag): everything goes into `./.claude/` — hook scripts, commands, and `settings.local.json` (gitignored). Good for shipping TTS config alongside a project. Each install gets its own daemon port, so multiple local-installed projects run independently without conflict.
47
47
  - `--global`: everything goes into `~/.claude/` — hook scripts, commands, and `settings.json`. Recommended for personal use across all projects.
48
48
 
49
49
  ### Option B — installer script
@@ -290,7 +290,9 @@ Type in the Claude Code prompt:
290
290
 
291
291
  ## Daemon Protocol
292
292
 
293
- The daemon runs on `localhost:6254` and accepts JSON lines:
293
+ The daemon runs on `localhost` on a port derived from the install directory (range 49152–65535). Each install location gets a stable, unique port — so multiple local-installed projects run independent daemons without conflict. Hook scripts and the daemon compute the same port, so they always find each other.
294
+
295
+ Accepts JSON lines:
294
296
 
295
297
  | Command | Effect |
296
298
  |---------|--------|
@@ -347,8 +349,8 @@ The daemon auto-restarts on the next Claude response.
347
349
  - sounddevice doesn't always pull in cffi automatically
348
350
 
349
351
  ### Daemon keeps restarting / won't stay up
350
- - Check for port conflict: `lsof -i :6254` (Mac/Linux) or `netstat -ano | findstr 6254` (Windows)
351
- - Check `~/.claude/hooks/tts/daemon.log`
352
+ - Each install uses a unique port derived from its directory path port conflicts between installs are not possible
353
+ - Check `daemon.log` in your hooks directory for errors
352
354
 
353
355
  ### Audio cuts off mid-sentence (kokoro fallback)
354
356
  - kokoro-onnx has a 510-token (~1500 char) hard limit
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@domdhi/claude-code-tts",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Neural TTS hook system for Claude Code. Reads Claude's responses aloud as they finish.",
5
5
  "bin": {
6
6
  "claude-code-tts": "bin/install.js"