diff --git a/README.md b/README.md index 5264cd7..e55757f 100644 --- a/README.md +++ b/README.md @@ -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 ` | insert literal text, **no** submit (read-before-send; say "send") | -| `space []` | insert n spaces (default 1) | +| `space []` (also `add [a] space`, `insert spaces`) | insert n spaces (default 1) | | `backspace []` (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 diff --git a/config.toml b/config.toml index 456b8f2..0d5c99d 100644 --- a/config.toml +++ b/config.toml @@ -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 diff --git a/src/claudedo/grammar.py b/src/claudedo/grammar.py index 7c69551..4fcce1e 100644 --- a/src/claudedo/grammar.py +++ b/src/claudedo/grammar.py @@ -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")