claude-can-speak 0.1.1 → 0.1.3
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/README.md +52 -21
- package/bin/claude-can-speak +90 -18
- package/bin/postinstall.js +29 -0
- package/commands/ccs.md +22 -0
- package/lib/claude-can-speak/tts-speak.sh +7 -18
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -8,15 +8,22 @@ when you have stepped away, a heads-up that a deploy needs confirmation, a short
|
|
|
8
8
|
shoutout you asked for, while everything else stays text-only. Selective, on
|
|
9
9
|
purpose, model-controlled.
|
|
10
10
|
|
|
11
|
-
If you *do* want the firehose, it is one
|
|
12
|
-
every finished reply,
|
|
13
|
-
|
|
14
|
-
point.
|
|
11
|
+
If you *do* want the firehose, it is one switch away: a Stop hook that speaks
|
|
12
|
+
every finished reply, with its own explicit on/off (`claude-can-speak on` /
|
|
13
|
+
`off`, off by default). But the deliberate skill is the point.
|
|
15
14
|
|
|
16
15
|
- **Deliberate mode (the headline)** - the `speak` skill lets Claude choose what
|
|
17
|
-
to voice.
|
|
18
|
-
- **Firehose mode (optional)** - a Stop hook speaks every reply
|
|
19
|
-
on
|
|
16
|
+
to voice. Active after `claude-can-speak setup`.
|
|
17
|
+
- **Firehose mode (optional)** - a Stop hook speaks every reply when you turn it
|
|
18
|
+
on with `claude-can-speak on` (off by default), or `/ccs on` from inside
|
|
19
|
+
Claude Code.
|
|
20
|
+
|
|
21
|
+
> **The toggle is a command, not a built-in slash setting.** claude-can-speak
|
|
22
|
+
> does not hook into Claude Code's `/voice`; if you type `/` in Claude Code
|
|
23
|
+
> before setup and find nothing, that is expected. Control the firehose from the
|
|
24
|
+
> terminal with `claude-can-speak on` / `off`, or from inside Claude Code with
|
|
25
|
+
> the `/ccs on` / `/ccs off` / `/ccs status` slash command that `setup`
|
|
26
|
+
> installs.
|
|
20
27
|
|
|
21
28
|
Speech is synthesised locally by [Kokoro](https://github.com/thewh1teagle/kokoro-onnx)
|
|
22
29
|
(natural English, the default) or [Piper](https://github.com/OHF-Voice/piper1-gpl)
|
|
@@ -37,40 +44,61 @@ network at speak time, no telemetry.
|
|
|
37
44
|
|
|
38
45
|
```sh
|
|
39
46
|
npm install -g claude-can-speak
|
|
40
|
-
|
|
41
|
-
# one-time: build the local TTS container image (needs Docker)
|
|
42
|
-
claude-can-speak build
|
|
47
|
+
claude-can-speak setup # Docker check, build image, install skill + hook
|
|
43
48
|
```
|
|
44
49
|
|
|
50
|
+
`setup` is the one command that does everything (it needs Docker). Then
|
|
51
|
+
**restart Claude Code once** so it loads the new skill and hook.
|
|
52
|
+
|
|
45
53
|
> If `npm install -g` fails with `EACCES` (a system-owned npm prefix like
|
|
46
54
|
> `/usr`), either use a user-level prefix once:
|
|
47
55
|
> `npm config set prefix ~/.npm-global && export PATH="$HOME/.npm-global/bin:$PATH"`
|
|
48
56
|
> (add that `export` to your shell profile), or install with `sudo`.
|
|
49
57
|
|
|
50
|
-
|
|
58
|
+
`setup` also installs a `/ccs` slash command into Claude Code, so the firehose
|
|
59
|
+
toggle is reachable from where you would instinctively look for it. **Restart
|
|
60
|
+
Claude Code once** after setup so it discovers the skill and the command.
|
|
61
|
+
|
|
62
|
+
After setup:
|
|
63
|
+
|
|
64
|
+
- **Deliberate mode** (the headline) is active: Claude can voice notifications
|
|
65
|
+
through the `speak` skill whenever it judges something worth hearing.
|
|
66
|
+
- **Firehose mode** (speak every reply) is **off by default**. Turn it on when
|
|
67
|
+
you want it, from the terminal or from inside Claude Code:
|
|
51
68
|
|
|
52
69
|
```sh
|
|
53
|
-
claude-can-speak
|
|
54
|
-
claude-can-speak
|
|
70
|
+
claude-can-speak on # speak every reply
|
|
71
|
+
claude-can-speak off # back to silent (default)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
/ccs on # same, from inside Claude Code
|
|
76
|
+
/ccs off
|
|
77
|
+
/ccs status
|
|
55
78
|
```
|
|
56
79
|
|
|
57
80
|
Models are downloaded on first use into `~/.cache/claude-can-speak/models`
|
|
58
81
|
(nothing model-shaped is bundled in the package; see
|
|
59
82
|
[THIRD_PARTY.md](THIRD_PARTY.md)).
|
|
60
83
|
|
|
61
|
-
|
|
84
|
+
Check everything with:
|
|
62
85
|
|
|
63
86
|
```sh
|
|
64
87
|
claude-can-speak status
|
|
65
88
|
claude-can-speak test # speak a sample line
|
|
66
89
|
```
|
|
67
90
|
|
|
91
|
+
If you prefer to do the steps by hand instead of `setup`: `claude-can-speak
|
|
92
|
+
build`, then `claude-can-speak install-skill` and/or `claude-can-speak
|
|
93
|
+
install-hooks`.
|
|
94
|
+
|
|
68
95
|
## Usage
|
|
69
96
|
|
|
70
97
|
```sh
|
|
71
98
|
claude-can-speak status # gate state, container, voice, model cache
|
|
72
99
|
claude-can-speak test [text] # speak a sample (or your text)
|
|
73
|
-
claude-can-speak
|
|
100
|
+
claude-can-speak on | off # firehose: speak every reply, or not (default off)
|
|
101
|
+
claude-can-speak say <text> # speak text now (always speaks; used by the skill)
|
|
74
102
|
claude-can-speak stop # interrupt whatever is being spoken
|
|
75
103
|
claude-can-speak voice <name> # set the default voice (e.g. af_heart)
|
|
76
104
|
claude-can-speak engine kokoro|piper
|
|
@@ -102,7 +130,7 @@ claude-can-speak voice tr_TR-dfki-medium # Turkish
|
|
|
102
130
|
## How it works
|
|
103
131
|
|
|
104
132
|
```
|
|
105
|
-
Claude Code reply ─▶ Stop hook (
|
|
133
|
+
Claude Code reply ─▶ Stop hook (when firehose on) ─▶ strip markdown & code
|
|
106
134
|
─▶ docker exec synth (Kokoro/Piper)
|
|
107
135
|
─▶ play WAV on the host
|
|
108
136
|
```
|
|
@@ -118,8 +146,11 @@ Per-user config lives in `~/.config/claude-can-speak/config.env` (written by the
|
|
|
118
146
|
`voice` / `engine` commands). Environment overrides: `CCS_IMAGE`,
|
|
119
147
|
`CCS_CONTAINER`, `CCS_MODELS_DIR`, `CLAUDE_SETTINGS`.
|
|
120
148
|
|
|
121
|
-
The
|
|
122
|
-
|
|
149
|
+
The firehose on/off state is a single file, `~/.config/claude-can-speak/firehose.enabled`
|
|
150
|
+
(present = on, absent = off), written by `claude-can-speak on` / `off`. It is
|
|
151
|
+
deliberately independent of Claude Code's `/voice`, which is speech-in dictation,
|
|
152
|
+
a separate concern. The `speak` skill is toggled via `skillOverrides` in
|
|
153
|
+
`~/.claude/settings.json`.
|
|
123
154
|
|
|
124
155
|
## Uninstall
|
|
125
156
|
|
|
@@ -154,9 +185,9 @@ aloud", any of those is a fine choice and lighter than this one (no Docker).
|
|
|
154
185
|
|
|
155
186
|
claude-can-speak is built around a different default: the deliberate `speak`
|
|
156
187
|
skill, so Claude voices only what is worth hearing rather than everything. It
|
|
157
|
-
also adds multilingual output (Piper for German, Turkish, and more)
|
|
158
|
-
isolation so the engines never touch your host Python
|
|
159
|
-
|
|
188
|
+
also adds multilingual output (Piper for German, Turkish, and more) and Docker
|
|
189
|
+
isolation so the engines never touch your host Python. The firehose mode is
|
|
190
|
+
included, with its own explicit on/off switch, but it is not the headline.
|
|
160
191
|
|
|
161
192
|
## Licence
|
|
162
193
|
|
package/bin/claude-can-speak
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# claude-can-speak: speech-out for Claude Code
|
|
2
|
+
# claude-can-speak: speech-out for Claude Code (deliberate skill + optional firehose).
|
|
3
3
|
#
|
|
4
4
|
# This CLI manages the TTS container and the playback lifecycle. The speaking
|
|
5
5
|
# itself is driven by a Stop hook (tts-speak.sh); this command is for setup,
|
|
@@ -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.3"
|
|
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}"
|
|
@@ -58,16 +59,18 @@ require_docker() {
|
|
|
58
59
|
|
|
59
60
|
cmd_help() {
|
|
60
61
|
cat <<EOF
|
|
61
|
-
claude-can-speak $VERSION - speech-out for Claude Code
|
|
62
|
+
claude-can-speak $VERSION - speech-out for Claude Code
|
|
62
63
|
|
|
63
64
|
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).
|
|
@@ -76,21 +79,28 @@ COMMANDS
|
|
|
76
79
|
install-hooks Register the Stop + interrupt hooks in settings.json.
|
|
77
80
|
remove-hooks Remove this project's hooks from settings.json.
|
|
78
81
|
install-skill Install the 'speak' skill into ~/.claude/skills.
|
|
82
|
+
install-command Install the '/ccs' slash command into ~/.claude/commands.
|
|
83
|
+
remove-command Remove the '/ccs' slash command.
|
|
79
84
|
skill on|off Enable/disable the 'speak' skill (settings skillOverrides).
|
|
80
85
|
build Build the TTS container image locally.
|
|
81
86
|
help | --help This text.
|
|
82
87
|
|
|
83
88
|
TWO MODES
|
|
84
|
-
|
|
85
|
-
(claude-can-speak
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
Deliberate (the headline): the 'speak' skill lets Claude choose what to
|
|
90
|
+
voice (notifications, shoutouts) via 'claude-can-speak say'.
|
|
91
|
+
Install with 'claude-can-speak install-skill'.
|
|
92
|
+
Firehose (optional): the Stop hook speaks every reply when the firehose is
|
|
93
|
+
on. Install the hook with 'claude-can-speak install-hooks', then
|
|
94
|
+
toggle with 'claude-can-speak on' / 'off' from the terminal, or
|
|
95
|
+
'/ccs on' / '/ccs off' from inside Claude Code (the /ccs slash
|
|
96
|
+
command is a convenience wrapper; run 'install-command' to add it).
|
|
89
97
|
|
|
90
98
|
GATING
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
The firehose has its own explicit on/off switch ('claude-can-speak on|off',
|
|
100
|
+
default OFF), stored in ~/.config/claude-can-speak/firehose.enabled. It is
|
|
101
|
+
intentionally NOT tied to Claude Code's /voice, which is speech-IN dictation
|
|
102
|
+
and is a separate concern. The deliberate 'speak' skill always speaks when
|
|
103
|
+
invoked, regardless of the firehose switch.
|
|
94
104
|
|
|
95
105
|
DISCLAIMER
|
|
96
106
|
Provided AS IS, with NO WARRANTY. You accept all risk. See the project
|
|
@@ -179,12 +189,11 @@ cmd_test() {
|
|
|
179
189
|
|
|
180
190
|
cmd_status() {
|
|
181
191
|
echo "claude-can-speak $VERSION"
|
|
182
|
-
printf '
|
|
183
|
-
if [ -f "$
|
|
184
|
-
|
|
185
|
-
echo "ON (/voice enabled)"
|
|
192
|
+
printf 'firehose : '
|
|
193
|
+
if [ -f "$ENABLED_FLAG" ]; then
|
|
194
|
+
echo "ON (replies spoken; 'claude-can-speak off' to silence)"
|
|
186
195
|
else
|
|
187
|
-
echo "off (
|
|
196
|
+
echo "off (replies silent; 'claude-can-speak on' to enable)"
|
|
188
197
|
fi
|
|
189
198
|
printf 'engine/voice : %s / %s (%s)\n' "$ENGINE" "$VOICE" "$LANG"
|
|
190
199
|
printf 'image : '; ensure_image && echo "$IMAGE present" || echo "$IMAGE MISSING (run: build)"
|
|
@@ -233,6 +242,45 @@ EOF
|
|
|
233
242
|
fi
|
|
234
243
|
}
|
|
235
244
|
|
|
245
|
+
cmd_on() {
|
|
246
|
+
mkdir -p "$CCS_HOME"
|
|
247
|
+
: > "$ENABLED_FLAG"
|
|
248
|
+
echo "firehose ON: replies will be spoken (needs the Stop hook; run install-hooks if you have not)."
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
cmd_off() {
|
|
252
|
+
rm -f "$ENABLED_FLAG" 2>/dev/null
|
|
253
|
+
# Also stop anything currently speaking.
|
|
254
|
+
cmd_stop >/dev/null 2>&1 || true
|
|
255
|
+
echo "firehose OFF: replies will not be spoken."
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
# One-shot setup: the happy path after `npm install -g`. Docker check, build the
|
|
259
|
+
# image, install the deliberate skill and the firehose hook. Idempotent.
|
|
260
|
+
cmd_setup() {
|
|
261
|
+
echo "claude-can-speak setup"
|
|
262
|
+
require_docker
|
|
263
|
+
echo "1/3 building the TTS container image (first time pulls deps, ~2 min) ..."
|
|
264
|
+
cmd_build
|
|
265
|
+
echo "2/4 installing the 'speak' skill ..."
|
|
266
|
+
cmd_install_skill
|
|
267
|
+
echo "3/4 installing the '/ccs' slash command ..."
|
|
268
|
+
cmd_install_command
|
|
269
|
+
echo "4/4 installing the firehose Stop hook ..."
|
|
270
|
+
cmd_install_hooks
|
|
271
|
+
cat <<EOF
|
|
272
|
+
|
|
273
|
+
Setup complete.
|
|
274
|
+
- Deliberate mode: Claude can voice notifications via the 'speak' skill (active now).
|
|
275
|
+
- Firehose mode: turn it on with 'claude-can-speak on' (off by default).
|
|
276
|
+
Restart Claude Code once so it loads the new skill, the /ccs command, and the
|
|
277
|
+
hook. After that you can toggle the firehose from inside Claude Code with
|
|
278
|
+
'/ccs on' and '/ccs off', or from the terminal:
|
|
279
|
+
claude-can-speak on
|
|
280
|
+
claude-can-speak test
|
|
281
|
+
EOF
|
|
282
|
+
}
|
|
283
|
+
|
|
236
284
|
cmd_install_skill() {
|
|
237
285
|
# Locate the packaged skill (deb vs git checkout).
|
|
238
286
|
local src
|
|
@@ -247,6 +295,25 @@ cmd_install_skill() {
|
|
|
247
295
|
echo "if ~/.claude/skills did not exist before, restart your session to discover it."
|
|
248
296
|
}
|
|
249
297
|
|
|
298
|
+
cmd_install_command() {
|
|
299
|
+
# Locate the packaged slash command (deb vs git checkout).
|
|
300
|
+
local src
|
|
301
|
+
for cand in "/usr/share/claude-can-speak/commands/ccs.md" "$SELF/../commands/ccs.md"; do
|
|
302
|
+
[ -f "$cand" ] && { src="$cand"; break; }
|
|
303
|
+
done
|
|
304
|
+
[ -n "${src:-}" ] || die "packaged slash command not found"
|
|
305
|
+
local dest="$HOME/.claude/commands/ccs.md"
|
|
306
|
+
mkdir -p "$(dirname "$dest")"
|
|
307
|
+
cp "$src" "$dest"
|
|
308
|
+
echo "installed '/ccs' slash command -> $dest"
|
|
309
|
+
echo "restart Claude Code once so it discovers the new command, then use /ccs status."
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
cmd_remove_command() {
|
|
313
|
+
local dest="$HOME/.claude/commands/ccs.md"
|
|
314
|
+
if [ -f "$dest" ]; then rm -f "$dest"; echo "removed '/ccs' slash command"; else echo "'/ccs' not installed"; fi
|
|
315
|
+
}
|
|
316
|
+
|
|
250
317
|
cmd_skill() {
|
|
251
318
|
case "${1:-}" in
|
|
252
319
|
on) _skill_override on; echo "'speak' skill enabled" ;;
|
|
@@ -280,6 +347,9 @@ cmd_remove_hooks() {
|
|
|
280
347
|
}
|
|
281
348
|
|
|
282
349
|
case "${1:-help}" in
|
|
350
|
+
setup) cmd_setup ;;
|
|
351
|
+
on) cmd_on ;;
|
|
352
|
+
off) cmd_off ;;
|
|
283
353
|
status) cmd_status ;;
|
|
284
354
|
test) shift; cmd_test "$@" ;;
|
|
285
355
|
say) shift; cmd_say "$@" ;;
|
|
@@ -292,6 +362,8 @@ case "${1:-help}" in
|
|
|
292
362
|
install-hooks) cmd_install_hooks ;;
|
|
293
363
|
remove-hooks) cmd_remove_hooks ;;
|
|
294
364
|
install-skill) cmd_install_skill ;;
|
|
365
|
+
install-command) cmd_install_command ;;
|
|
366
|
+
remove-command) cmd_remove_command ;;
|
|
295
367
|
skill) shift; cmd_skill "${1:-}" ;;
|
|
296
368
|
build) cmd_build ;;
|
|
297
369
|
help|-h|--help) cmd_help ;;
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
" the '/ccs' slash command, and the optional firehose hook.",
|
|
20
|
+
" Then restart Claude Code once.",
|
|
21
|
+
"",
|
|
22
|
+
" Deliberate mode (Claude voices notifications) is on after setup.",
|
|
23
|
+
" Firehose mode (speak every reply) is off by default. Turn it on from the",
|
|
24
|
+
" terminal with 'claude-can-speak on', or inside Claude Code with '/ccs on'.",
|
|
25
|
+
"",
|
|
26
|
+
" Provided AS IS, no warranty. https://ra-yavuz.github.io/claude-can-speak/",
|
|
27
|
+
"",
|
|
28
|
+
];
|
|
29
|
+
process.stdout.write(L.join("\n") + "\n");
|
package/commands/ccs.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Control claude-can-speak (status / on / off)
|
|
3
|
+
argument-hint: [status|on|off]
|
|
4
|
+
allowed-tools: Bash(claude-can-speak:*)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The user invoked the claude-can-speak control command with argument: "$ARGUMENTS"
|
|
8
|
+
|
|
9
|
+
Run the matching CLI command and report the result plainly. The argument is one
|
|
10
|
+
of `status` (default if empty), `on`, or `off`:
|
|
11
|
+
|
|
12
|
+
- empty or `status` -> show current state:
|
|
13
|
+
!`claude-can-speak status`
|
|
14
|
+
- `on` -> turn the speak-every-reply firehose on:
|
|
15
|
+
!`if [ "$ARGUMENTS" = "on" ]; then claude-can-speak on; fi`
|
|
16
|
+
- `off` -> turn the firehose off (replies go silent again):
|
|
17
|
+
!`if [ "$ARGUMENTS" = "off" ]; then claude-can-speak off; fi`
|
|
18
|
+
|
|
19
|
+
Note for the user if relevant: `claude-can-speak` is a terminal command too; this
|
|
20
|
+
slash command is just a convenience wrapper so the firehose toggle is reachable
|
|
21
|
+
from inside Claude Code. The firehose hook hot-reloads, so `on`/`off` take effect
|
|
22
|
+
on the next reply without restarting the session.
|
|
@@ -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.3",
|
|
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,12 +28,17 @@
|
|
|
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/",
|
|
36
40
|
"skills/",
|
|
41
|
+
"commands/",
|
|
37
42
|
"THIRD_PARTY.md",
|
|
38
43
|
"LICENSE",
|
|
39
44
|
"README.md"
|