claude-can-speak 0.1.1 → 0.1.2
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.
- package/bin/claude-can-speak +59 -16
- package/bin/postinstall.js +28 -0
- package/lib/claude-can-speak/tts-speak.sh +7 -18
- package/package.json +5 -1
package/bin/claude-can-speak
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
# any damage or loss arising from its use. By using it you accept all risk.
|
|
10
10
|
set -uo pipefail
|
|
11
11
|
|
|
12
|
-
VERSION="0.1.
|
|
12
|
+
VERSION="0.1.2"
|
|
13
13
|
|
|
14
14
|
# Install layout: bundled scripts live in ../lib/claude-can-speak relative to
|
|
15
15
|
# this CLI, whether installed via npm (into the global node_modules) or run from
|
|
@@ -27,6 +27,7 @@ LIBEXEC="$SELF/../lib/claude-can-speak"
|
|
|
27
27
|
CCS_HOME="${CCS_HOME:-$HOME/.config/claude-can-speak}"
|
|
28
28
|
CONFIG="$CCS_HOME/config.env"
|
|
29
29
|
PIDFILE="$CCS_HOME/speaking.pid"
|
|
30
|
+
ENABLED_FLAG="$CCS_HOME/firehose.enabled"
|
|
30
31
|
CONTAINER="${CCS_CONTAINER:-ccs-tts}"
|
|
31
32
|
IMAGE="${CCS_IMAGE:-claude-can-speak:latest}"
|
|
32
33
|
MODELS_DIR="${CCS_MODELS_DIR:-$HOME/.cache/claude-can-speak/models}"
|
|
@@ -64,10 +65,12 @@ USAGE
|
|
|
64
65
|
claude-can-speak <command> [args]
|
|
65
66
|
|
|
66
67
|
COMMANDS
|
|
67
|
-
|
|
68
|
+
setup One-shot install: Docker check, build, skill, hook.
|
|
69
|
+
on | off Turn the firehose (speak every reply) on or off. Default off.
|
|
70
|
+
status Show firehose state, container, config, and model cache.
|
|
68
71
|
test [text] Speak a sample (or the given text) with the current voice.
|
|
69
72
|
stop Interrupt any reply currently being spoken.
|
|
70
|
-
say <text> Speak arbitrary text now (
|
|
73
|
+
say <text> Speak arbitrary text now (always speaks; used by the skill).
|
|
71
74
|
start | up Start the persistent TTS container.
|
|
72
75
|
stop-container Stop and remove the TTS container.
|
|
73
76
|
voice <name> Set the default voice (e.g. af_heart, af_bella).
|
|
@@ -81,16 +84,19 @@ COMMANDS
|
|
|
81
84
|
help | --help This text.
|
|
82
85
|
|
|
83
86
|
TWO MODES
|
|
84
|
-
|
|
85
|
-
(claude-can-speak
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
Deliberate (the headline): the 'speak' skill lets Claude choose what to
|
|
88
|
+
voice (notifications, shoutouts) via 'claude-can-speak say'.
|
|
89
|
+
Install with 'claude-can-speak install-skill'.
|
|
90
|
+
Firehose (optional): the Stop hook speaks every reply when the firehose is
|
|
91
|
+
on. Install the hook with 'claude-can-speak install-hooks', then
|
|
92
|
+
toggle with 'claude-can-speak on' / 'off'.
|
|
89
93
|
|
|
90
94
|
GATING
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
The firehose has its own explicit on/off switch ('claude-can-speak on|off',
|
|
96
|
+
default OFF), stored in ~/.config/claude-can-speak/firehose.enabled. It is
|
|
97
|
+
intentionally NOT tied to Claude Code's /voice, which is speech-IN dictation
|
|
98
|
+
and is a separate concern. The deliberate 'speak' skill always speaks when
|
|
99
|
+
invoked, regardless of the firehose switch.
|
|
94
100
|
|
|
95
101
|
DISCLAIMER
|
|
96
102
|
Provided AS IS, with NO WARRANTY. You accept all risk. See the project
|
|
@@ -179,12 +185,11 @@ cmd_test() {
|
|
|
179
185
|
|
|
180
186
|
cmd_status() {
|
|
181
187
|
echo "claude-can-speak $VERSION"
|
|
182
|
-
printf '
|
|
183
|
-
if [ -f "$
|
|
184
|
-
|
|
185
|
-
echo "ON (/voice enabled)"
|
|
188
|
+
printf 'firehose : '
|
|
189
|
+
if [ -f "$ENABLED_FLAG" ]; then
|
|
190
|
+
echo "ON (replies spoken; 'claude-can-speak off' to silence)"
|
|
186
191
|
else
|
|
187
|
-
echo "off (
|
|
192
|
+
echo "off (replies silent; 'claude-can-speak on' to enable)"
|
|
188
193
|
fi
|
|
189
194
|
printf 'engine/voice : %s / %s (%s)\n' "$ENGINE" "$VOICE" "$LANG"
|
|
190
195
|
printf 'image : '; ensure_image && echo "$IMAGE present" || echo "$IMAGE MISSING (run: build)"
|
|
@@ -233,6 +238,41 @@ EOF
|
|
|
233
238
|
fi
|
|
234
239
|
}
|
|
235
240
|
|
|
241
|
+
cmd_on() {
|
|
242
|
+
mkdir -p "$CCS_HOME"
|
|
243
|
+
: > "$ENABLED_FLAG"
|
|
244
|
+
echo "firehose ON: replies will be spoken (needs the Stop hook; run install-hooks if you have not)."
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
cmd_off() {
|
|
248
|
+
rm -f "$ENABLED_FLAG" 2>/dev/null
|
|
249
|
+
# Also stop anything currently speaking.
|
|
250
|
+
cmd_stop >/dev/null 2>&1 || true
|
|
251
|
+
echo "firehose OFF: replies will not be spoken."
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
# One-shot setup: the happy path after `npm install -g`. Docker check, build the
|
|
255
|
+
# image, install the deliberate skill and the firehose hook. Idempotent.
|
|
256
|
+
cmd_setup() {
|
|
257
|
+
echo "claude-can-speak setup"
|
|
258
|
+
require_docker
|
|
259
|
+
echo "1/3 building the TTS container image (first time pulls deps, ~2 min) ..."
|
|
260
|
+
cmd_build
|
|
261
|
+
echo "2/3 installing the 'speak' skill ..."
|
|
262
|
+
cmd_install_skill
|
|
263
|
+
echo "3/3 installing the firehose Stop hook ..."
|
|
264
|
+
cmd_install_hooks
|
|
265
|
+
cat <<EOF
|
|
266
|
+
|
|
267
|
+
Setup complete.
|
|
268
|
+
- Deliberate mode: Claude can voice notifications via the 'speak' skill (active now).
|
|
269
|
+
- Firehose mode: turn it on with 'claude-can-speak on' (off by default).
|
|
270
|
+
Restart Claude Code once so it loads the new skill and hook, then try:
|
|
271
|
+
claude-can-speak on
|
|
272
|
+
claude-can-speak test
|
|
273
|
+
EOF
|
|
274
|
+
}
|
|
275
|
+
|
|
236
276
|
cmd_install_skill() {
|
|
237
277
|
# Locate the packaged skill (deb vs git checkout).
|
|
238
278
|
local src
|
|
@@ -280,6 +320,9 @@ cmd_remove_hooks() {
|
|
|
280
320
|
}
|
|
281
321
|
|
|
282
322
|
case "${1:-help}" in
|
|
323
|
+
setup) cmd_setup ;;
|
|
324
|
+
on) cmd_on ;;
|
|
325
|
+
off) cmd_off ;;
|
|
283
326
|
status) cmd_status ;;
|
|
284
327
|
test) shift; cmd_test "$@" ;;
|
|
285
328
|
say) shift; cmd_say "$@" ;;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Printed once after `npm install -g claude-can-speak`. Deliberately does NO
|
|
3
|
+
// heavy or side-effecting work (no docker build, no editing ~/.claude): it only
|
|
4
|
+
// tells the user the single next command. The real setup is explicit and
|
|
5
|
+
// user-chosen, which keeps `npm install` fast, quiet, and unsurprising.
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
// Skip the banner in CI / non-interactive installs to avoid log noise.
|
|
9
|
+
if (process.env.CI || process.env.npm_config_loglevel === "silent") process.exit(0);
|
|
10
|
+
|
|
11
|
+
const L = [
|
|
12
|
+
"",
|
|
13
|
+
" claude-can-speak installed.",
|
|
14
|
+
"",
|
|
15
|
+
" One more step (needs Docker):",
|
|
16
|
+
" claude-can-speak setup",
|
|
17
|
+
"",
|
|
18
|
+
" That builds the local TTS container and installs the 'speak' skill",
|
|
19
|
+
" plus the optional firehose hook. Then restart Claude Code once.",
|
|
20
|
+
"",
|
|
21
|
+
" Deliberate mode (Claude voices notifications) is on after setup.",
|
|
22
|
+
" Firehose mode (speak every reply) is off by default; turn it on with:",
|
|
23
|
+
" claude-can-speak on",
|
|
24
|
+
"",
|
|
25
|
+
" Provided AS IS, no warranty. https://ra-yavuz.github.io/claude-can-speak/",
|
|
26
|
+
"",
|
|
27
|
+
];
|
|
28
|
+
process.stdout.write(L.join("\n") + "\n");
|
|
@@ -17,7 +17,6 @@ set -uo pipefail
|
|
|
17
17
|
# --- Resolve config -------------------------------------------------------
|
|
18
18
|
CCS_HOME="${CCS_HOME:-$HOME/.config/claude-can-speak}"
|
|
19
19
|
CCS_CONFIG="$CCS_HOME/config.env"
|
|
20
|
-
SETTINGS_JSON="${CLAUDE_SETTINGS:-$HOME/.claude/settings.json}"
|
|
21
20
|
CONTAINER="${CCS_CONTAINER:-ccs-tts}"
|
|
22
21
|
IMAGE="${CCS_IMAGE:-claude-can-speak:latest}"
|
|
23
22
|
MODELS_DIR="${CCS_MODELS_DIR:-$HOME/.cache/claude-can-speak/models}"
|
|
@@ -51,23 +50,13 @@ done
|
|
|
51
50
|
# --- Read the Stop hook payload ------------------------------------------
|
|
52
51
|
PAYLOAD="$(cat)"
|
|
53
52
|
|
|
54
|
-
# --- Gate: only speak when
|
|
55
|
-
#
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"$SETTINGS_JSON" 2>/dev/null)"
|
|
62
|
-
[ "$v" = "true" ]
|
|
63
|
-
return
|
|
64
|
-
fi
|
|
65
|
-
# jq-less fallback: grep the two known keys.
|
|
66
|
-
grep -Eq '"voiceEnabled"[[:space:]]*:[[:space:]]*true' "$SETTINGS_JSON" && return 0
|
|
67
|
-
grep -Eq '"enabled"[[:space:]]*:[[:space:]]*true' "$SETTINGS_JSON" && return 0
|
|
68
|
-
return 1
|
|
69
|
-
}
|
|
70
|
-
voice_on || { log "voice gate off; silent"; exit 0; }
|
|
53
|
+
# --- Gate: only speak when the firehose is explicitly ON ------------------
|
|
54
|
+
# claude-can-speak owns its own on/off state, decoupled from Claude Code's
|
|
55
|
+
# /voice (which is speech-IN dictation and is not reliably readable here).
|
|
56
|
+
# Default is OFF: the state file exists only when the user ran
|
|
57
|
+
# `claude-can-speak on`. This guarantees a real, predictable off-switch.
|
|
58
|
+
ENABLED_FLAG="${CCS_ENABLED_FLAG:-$CCS_HOME/firehose.enabled}"
|
|
59
|
+
[ -f "$ENABLED_FLAG" ] || { log "firehose off; silent"; exit 0; }
|
|
71
60
|
|
|
72
61
|
# --- Extract the reply text ----------------------------------------------
|
|
73
62
|
extract_text() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-can-speak",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Let Claude Code decide what to say out loud: a skill that voices deliberate notifications (not every reply), plus an optional speak-everything Stop hook. Local neural TTS via Kokoro/Piper in Docker, gated on /voice.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -28,8 +28,12 @@
|
|
|
28
28
|
"bin": {
|
|
29
29
|
"claude-can-speak": "bin/cli.js"
|
|
30
30
|
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"postinstall": "node bin/postinstall.js"
|
|
33
|
+
},
|
|
31
34
|
"files": [
|
|
32
35
|
"bin/cli.js",
|
|
36
|
+
"bin/postinstall.js",
|
|
33
37
|
"bin/claude-can-speak",
|
|
34
38
|
"lib/claude-can-speak/",
|
|
35
39
|
"container/",
|