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 ## Command grammar
Wake phrases (listen mode), fuzzy-matched. The default list is **"claudedo"**, Wake phrases (listen mode), fuzzy-matched. The default list is **"claudedo"**,
**"claude do"**, **"claude due"**, **"hey claude"**, **"ok claude"**, **"okay **"claude do"**, **"hey claude"**, **"ok claude"**, **"okay claude"** — Whisper has
claude"** — Whisper has no token for the coined word "claudedo" and renders it as no token for the coined word "claudedo" and renders it as real words ("claude do"),
real words ("claude do"/"claude due"), so those spellings are listed explicitly. so that spelling is listed explicitly. Matching is lenient (case/space-insensitive).
Matching is lenient (case/space-insensitive). Add the spellings you actually see Add the spellings you actually see (turn on `print_heard` to find them). In PTT mode
(turn on `print_heard` to find them). In PTT mode the wake phrase is optional. the wake phrase is optional.
| Say | Does | | 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 | | `approve` / `deny` | allow / deny a permission prompt |
| `send` / `enter` | submit (Enter) | | `send` / `enter` | submit (Enter) |
| `type <phrase>` | insert literal text, **no** submit (read-before-send; say "send") | | `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 | | `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 | | `erase` (alias `clear`/`wipe`) | delete everything typed since the last submit/boundary |
| `mode ptt` / `mode listen` | switch input mode | | `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 - **`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 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 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 ## Requirements

View File

@ -5,7 +5,7 @@
# wake phrases for listen mode. fuzzy-matched: case/space-insensitive, lenient on # wake phrases for listen mode. fuzzy-matched: case/space-insensitive, lenient on
# the coined word "claudedo" (whisper renders it inconsistently). number words are # the coined word "claudedo" (whisper renders it inconsistently). number words are
# normalized to digits before command matching. # 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] [input]
# "listen" (default): continuous capture; only acts on utterances that start with a # "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): if _fuzzy_in(head, ("backspace", "delete"), threshold):
return Action("backspace", _leading_count(rest, default=1)) 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)) 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): if _fuzzy_in(head, ("erase", "clear", "wipe"), threshold):
return Action("erase") return Action("erase")