feat: 'add [a] space' / 'insert <n> spaces' phrasing; drop 'claude due' wake

map 'add a space'/'add space'/'insert two spaces' to the space command (count read
from either side of the noun). remove 'claude due' from the default wake list (it
double-rendered with 'claude do' and wasn't wanted). docs synced.

Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
disqualifier 2026-06-26 01:27:16 -04:00
parent 08bbe3ce58
commit bd6597352a
3 changed files with 15 additions and 9 deletions

View File

@ -102,11 +102,11 @@ Switch at runtime by voice: "claudedo mode listen" / "claudedo mode ptt".
## Command grammar
Wake phrases (listen mode), fuzzy-matched. The default list is **"claudedo"**,
**"claude do"**, **"claude due"**, **"hey claude"**, **"ok claude"**, **"okay
claude"** — Whisper has no token for the coined word "claudedo" and renders it as
real words ("claude do"/"claude due"), so those spellings are listed explicitly.
Matching is lenient (case/space-insensitive). Add the spellings you actually see
(turn on `print_heard` to find them). In PTT mode the wake phrase is optional.
**"claude do"**, **"hey claude"**, **"ok claude"**, **"okay claude"** — Whisper has
no token for the coined word "claudedo" and renders it as real words ("claude do"),
so that spelling is listed explicitly. Matching is lenient (case/space-insensitive).
Add the spellings you actually see (turn on `print_heard` to find them). In PTT mode
the wake phrase is optional.
| Say | Does |
|---|---|
@ -115,7 +115,7 @@ Matching is lenient (case/space-insensitive). Add the spellings you actually see
| `approve` / `deny` | allow / deny a permission prompt |
| `send` / `enter` | submit (Enter) |
| `type <phrase>` | insert literal text, **no** submit (read-before-send; say "send") |
| `space [<n>]` | insert n spaces (default 1) |
| `space [<n>]` (also `add [a] space`, `insert <n> spaces`) | insert n spaces (default 1) |
| `backspace [<n>]` (alias `delete`) | delete n chars (default 1), capped at the last submit boundary |
| `erase` (alias `clear`/`wipe`) | delete everything typed since the last submit/boundary |
| `mode ptt` / `mode listen` | switch input mode |
@ -195,7 +195,7 @@ key, Whisper model/language/device, audio segmentation thresholds, and `[behavio
- **`print_heard`** (default `false`, debug): prints non-wake transcripts to the
console so you can see how Whisper renders your wake word. Turn it on to debug
detection, then off. Whisper has no token for "claudedo" — it commonly emits
"claude do" or "claude due", both of which are in the default wake list.
"claude do", which is in the default wake list.
## Requirements

View File

@ -5,7 +5,7 @@
# wake phrases for listen mode. fuzzy-matched: case/space-insensitive, lenient on
# the coined word "claudedo" (whisper renders it inconsistently). number words are
# normalized to digits before command matching.
phrases = ["claudedo", "claude do", "claude due", "hey claude", "ok claude", "okay claude"]
phrases = ["claudedo", "claude do", "hey claude", "ok claude", "okay claude"]
[input]
# "listen" (default): continuous capture; only acts on utterances that start with a

View File

@ -185,8 +185,14 @@ def match_command(remainder: str, threshold: float) -> Action | None:
if _fuzzy_in(head, ("backspace", "delete"), threshold):
return Action("backspace", _leading_count(rest, default=1))
if _fuzzy_in(head, ("space",), threshold):
if _fuzzy_in(head, ("space", "spacebar"), threshold):
return Action("space", _leading_count(rest, default=1))
if _fuzzy_in(head, ("add", "insert"), threshold) and rest:
tail = [t for t in rest if t not in ("a", "an")]
if any(_fuzzy_in(t, ("space", "spaces"), threshold) for t in tail):
count = next((int(t) for t in tail if t.isdigit()),
next((_COUNT_WORDS[t] for t in tail if t in _COUNT_WORDS), 1))
return Action("space", count)
if _fuzzy_in(head, ("erase", "clear", "wipe"), threshold):
return Action("erase")