|
1 | 1 | # sag-notify |
2 | 2 |
|
3 | | -Spoken voice notifications for Claude Code via [`sag`](https://github.com/) (ElevenLabs TTS). |
| 3 | +Spoken voice notifications for Claude Code via [`sag`](https://github.com/steipete/sag) (ElevenLabs TTS). |
4 | 4 |
|
5 | 5 | - **Needs you** → when Claude waits for permission/input, it speaks a short alert naming the project. |
6 | 6 | - **Turn done** → when Claude finishes substantive work, it speaks a one-line summary you author. |
7 | 7 |
|
8 | 8 | Both are driven by **auto-injected hooks** — once the plugin is enabled, every session gets them, no per-session setup. |
9 | 9 |
|
| 10 | +## Requirements |
| 11 | + |
| 12 | +The `sag` CLI must be installed and authenticated. Install with `brew install steipete/tap/sag` and set `ELEVENLABS_API_KEY`. Full guide: [skills/sag-voice/references/sag-cli.md](skills/sag-voice/references/sag-cli.md). |
| 13 | + |
10 | 14 | ## How it works |
11 | 15 |
|
12 | 16 | | Event | Hook | Behavior | |
13 | 17 | |-------|------|----------| |
14 | | -| `Notification` | `hooks/notify.sh` | Speaks `templates.notification` with the project name. The harness message is English, so it's replaced by your (Vietnamese by default) template. | |
15 | | -| `Stop` | `hooks/summary.sh` | Reads the body Claude wrote to `summary_file`, speaks it via `templates.summary`, deletes the file. **Silent when no file exists**, so trivial turns are quiet. | |
| 18 | +| `Notification` | `hooks/notify.sh` | Speaks the notification template, naming the project, in the configured language. (The harness message is English, so it is replaced by the template.) | |
| 19 | +| `Stop` | `hooks/summary.sh` | Reads the body Claude wrote to `summary_file`, speaks it via the summary template, deletes the file. **Silent when no file exists**, so trivial turns are quiet. | |
16 | 20 |
|
17 | | -To make Claude speak a summary, it writes a short body to `~/.claude/.sag-summary` during a substantive turn. The hook adds the `Đây là Claude, project <name>.` prefix. |
| 21 | +To make Claude speak a summary, it writes a short body to `~/.claude/.sag-summary` during a substantive turn. The hook adds the `This is <name>, reporting from project <name>:` framing automatically. |
18 | 22 |
|
19 | 23 | ## Setup |
20 | 24 |
|
21 | | -1. Enable the plugin (it ships `hooks/hooks.json`). |
22 | | -2. Run `/sag-notify:setup` — checks `sag`/`jq`, resolves the API key, picks a voice, writes config, and tests audio. |
23 | | -3. Or just rely on defaults: Brian voice, Vietnamese, key from `~/.secret`. |
| 25 | +1. Install + authenticate `sag` (see Requirements). |
| 26 | +2. Enable the plugin (it ships `hooks/hooks.json`). |
| 27 | +3. Run `/sag-notify:setup` — checks `sag`/`jq`, resolves the API key, picks a voice, writes config, and tests audio. |
| 28 | +4. Or just rely on defaults: Brian voice, English templates, key from the `ELEVENLABS_API_KEY` environment variable. |
24 | 29 |
|
25 | | -`ELEVENLABS_API_KEY` must be resolvable — from the env or the configured `key_file` (default `~/.secret`). |
| 30 | +`ELEVENLABS_API_KEY` must be resolvable — from the environment, or from an optional key file you point `key_file` at in your user config. |
26 | 31 |
|
27 | 32 | ## Configuration |
28 | 33 |
|
29 | | -User config at `~/.config/sag-notify/config.json` overrides [`config.default.json`](config.default.json). See the **sag-voice** skill or run `/sag-notify:config`. Key settings: `enabled`, `events.{notification,summary}`, `voice_id`, `model_id`, `self_name`, `language`, `key_file`, `summary_file`, `error_log`, `max_chars`, `templates.{notification,summary}`. |
| 34 | +User config at `~/.config/sag-notify/config.json` overrides [`config.default.json`](config.default.json). See the **sag-voice** skill or run `/sag-notify:config`. Key settings: `enabled`, `events.{notification,summary}`, `voice_id`, `model_id`, `self_name`, `language`, `key_file`, `summary_file`, `error_log`, `max_chars`, `templates.{notification,summary}`, `languages.<lang>.{notification,summary}`. |
| 35 | + |
| 36 | +### Languages |
| 37 | + |
| 38 | +Set `language` to pick a built-in preset. `en` and `vi` ship by default; add more under `languages.<lang>` (placeholders `{name}`, `{project}`, `{body}`). Resolution: explicit `templates.<kind>` override → `languages.<language>.<kind>` → `languages.en.<kind>`. |
| 39 | + |
| 40 | +```bash |
| 41 | +jq '.language = "vi"' ~/.config/sag-notify/config.json > /tmp/c && mv /tmp/c ~/.config/sag-notify/config.json |
| 42 | +``` |
30 | 43 |
|
31 | 44 | ### Voice tiers (important) |
32 | 45 |
|
33 | | -`premade` voices work on the **free** ElevenLabs tier. `professional`/library voices (e.g. the native Vietnamese "Minh Trung" `FTYCiQT21H9XQvhRu0ch`) return **402 Payment Required** unless you upgrade. Default is **Brian** (`nPczCjzI2devNBz1zQrb`, premade) speaking Vietnamese via the multilingual `eleven_flash_v2_5` model. |
| 46 | +`premade` voices work on the **free** ElevenLabs tier. `professional`/library voices return **402 Payment Required** unless you upgrade your plan. The default is **Brian** (`nPczCjzI2devNBz1zQrb`, premade); `eleven_flash_v2_5` is multilingual so a premade voice can speak any language (with an accent). Run `sag voices` to list what your key can use. |
34 | 47 |
|
35 | 48 | ## Commands |
36 | 49 |
|
|
0 commit comments