Commit Graph

29 Commits

Author SHA1 Message Date
5f05a01423 feat: v0.1.4 — HELP menu, 15s cap, wake 0.65, small.en default + docs sync
commands menu now prints under a single [HELP] header with bare indented rows
(brightblue usage) instead of 15 repeated [SYSTEM] tags. raise [vad].max_seconds
10 -> 15 for long dictation. wake_fuzzy_threshold 0.6 -> 0.65 (slightly fewer false
wakes; note short spellings 'ok/okay claude' still admit some). carries the prior
small.en default, [vad].silence_ms 700, lighter (brightblue) command color, lean
injection lines, .en model variants in the validator. README/CLAUDE.md synced.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 03:52:19 -04:00
e84ef91e7b tune: small.en default, vad 700ms, lighter command color, lean inject lines
default model -> small.en (english-only small; better english accuracy, same ~1s
latency; .en variants added to the validator). raise [vad].silence_ms 500 -> 700
(500 cut off too early). command words now brightblue (lighter/cyan-ish) instead of
dark blue. drop the redundant target from injection lines — the [session] prefix
already names it, so e.g. '[claude-testing] typed ...' not '... sticky claude-testing
-> typed ...'.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 03:41:46 -04:00
2cbbabfaa1 feat: unbounded backspace + blue command words in console
backspace now sends exactly n BSpace with no boundary cap (buffer floored at 0 so a
later erase stays correct); erase remains bound to the uncommitted-input buffer. add
a blue color and Console.paint(); paint the command word blue on SYSTEM lines
(list/set/unset/mode -> ...) so the action stands out.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 03:11:42 -04:00
4357b14fad perf: default back to small model; show per-command STT latency
medium added ~3s/command lag (measured ~1.2s small vs ~3s medium on a 7950X3D), so
default model -> small; lean on initial_prompt + lenient wake for the coined word.
every heard line now shows STT latency as (<ms>/<audio>s) — always on, not just
print_heard — so a model change's cost is visible. snappier vad (silence_ms 500)
from the prior commit stands.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 02:57:52 -04:00
8e20b7eb0b feat: commands/customs menu, green heard-echo, snappier VAD
add voice 'commands' (alias help/menu) printing the command menu and 'customs'
(alias custom) stubbed for v0.2.0. echo every recognized command as a green
'heard "..." -> ACTION' line before acting, so you see what landed; the result line
then reports target + keystrokes. lower [vad].silence_ms default 800 -> 500 for a
snappier endpoint after you stop talking.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 02:32:28 -04:00
4abdfd56bc feat: start skips the mic check by default; --check to opt in
invert the pre-listen mic check — default is no check (just start listening); pass
'claudedo start --check' to run it. replaces the old --skip-audio-check flag.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 02:25:20 -04:00
e6dadab143 feat: debug/echo command — print the spoken phrase to the console
'<wake> debug <text>' (alias echo) echoes what you said to the console as
[VOICE] debug: "..." and injects nothing — a no-target test command for checking
wake + STT transcription. added to the STT vocab so it's biased for.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 02:22:37 -04:00
5064f912a4 fix: install.sh installs config.toml to ~/.config/claudedo
the daemon's config lookup falls through to ./config.toml only, so without a copy in
the standard dir it was repo-cwd-only. install config.toml to ~/.config/claudedo/ —
copy if absent, else write config.toml.new beside the user's edited copy (never
clobber). also gitignore COMPACT.md (handoff doc kept on disk, untracked).

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 01:53:25 -04:00
a51c2fbdd4 feat: v0.1.3 STT tuning — medium model, initial_prompt bias, split thresholds, VAD config
default stt.model -> medium (biggest accuracy gain for the coined wake word;
small/large-v3 documented alternatives). seed faster-whisper with an initial_prompt
derived from the configured wake phrases + command vocabulary (grammar.vocabulary /
initial_prompt, one source — command synonyms now live in named _*_VERBS tuples).

split the single fuzzy threshold into wake_fuzzy_threshold (0.6, lenient — a false
wake is cheap) and command_fuzzy_threshold (0.8, tight — a false command fires the
wrong action); grammar.parse() takes both. add a [vad] config section (silence_ms,
max_seconds) for the existing Alexa-style record-until-pause endpointing, which
captures a command whole and lets the trailing pause separate it from following
chatter (that chatter is a separate capture the wake gate discards). bump to 0.1.3.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 01:41:48 -04:00
bd6597352a 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>
2026-06-26 01:27:16 -04:00
08bbe3ce58 docs: sync README with v0.1.2 (wake list, editing cmds, auto_target, console)
reconcile README with the shipped code and with CLAUDE.md: full 6-phrase wake list
(claudedo/claude do/claude due/hey claude/ok claude/okay claude) with the Whisper
rationale; space/backspace/erase in the grammar + flow; colored prefixed console
output description; fix the auto_target contradiction (default false = require
set/target, not auto-pick); drop the stale 'backgroundable'.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 01:22:00 -04:00
d96dc3898f feat: backspace/space/erase editing commands + colored prefixed console
voice editing: 'space [<n>]' inserts spaces, 'backspace [<n>]' (alias delete)
deletes chars, 'erase' (alias clear/wipe) wipes the current input. the daemon
tracks a per-session uncommitted-input char count so backspace is capped at the
last submit boundary and erase clears exactly back to it; submit/set reset it.
keys.py gains BSpace/space; grammar gains a count parser (digits + number words).

new console.py renders every daemon line as 'HH:MM:SS [prefix] message' with
color: [<session>] for injected lines (green), [SYSTEM] for state, [VOICE] for
recognition/drops (red/dim). bump to 0.1.2.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 01:17:22 -04:00
d734161c97 feat: auto_target toggle, print_heard debug, more wake spellings
add behavior.auto_target (default false): with no sticky target and exactly one
session running, false requires an explicit set/target rather than guessing; true
auto-uses it. target.resolve() takes the flag. add behavior.print_heard (default
false, debug): opt-in console echo of non-wake transcripts to see how Whisper
renders the wake word. add behavior.filler_words. expand the wake list with the
spellings Whisper actually emits for the coined word ('claude do', 'claude due',
'ok claude', 'okay claude').

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 01:17:08 -04:00
b05f6256c1 fix: quiet onnxruntime GPU-discovery warning and faster_whisper INFO
faster-whisper's VAD loads an onnx model that prints a 'GPU device discovery
failed' warning on headless/WSL hosts and chatty INFO per transcribe. raise onnx
log severity, drop the faster_whisper logger to WARNING, and filter the C++-level
discovery line out of stderr during model load + a one-shot warm transcribe (so it
fires once at startup, not in the hot loop). real errors still pass through.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-26 01:16:47 -04:00
43b36d2a0b feat: v0.1.1 sticky vs one-shot targeting, filler words, auto-single
redefine targeting: 'set' (aliases sticky/switch) is the persistent sticky
default (~/.claude-active); 'target <name> <command>' is a one-shot override that
routes a single command without changing the sticky default. add 'unset' and
'list'. resolution moves to a single target.resolve(one_shot) implementing the
order: one-shot -> sticky-if-exists -> only-session auto -> ambiguous/none do
nothing (never falls through, never injects into a missing session).

grammar.parse now returns ParsedCommand(one_shot, action) and skips optional
leading filler words (config behavior.filler_words: select/use/choose), with a
filler-before-digit still meaning the select command. CLI gains set/unset/list
(switch kept as a set alias). daemon console shows the targeting reason per line.
docs updated; no stale 'target = sticky' wording remains. bump to 0.1.1.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 20:16:29 -04:00
17db65858e feat: terminal-run only — drop systemd/autostart, start does mic-check + visible loop
terminal-run is the product, so remove all backgrounding: delete the
claudedo.service unit and autostart.sh, strip the systemd step and the
autostart source-line from install.sh (rc block now sources cc.sh only).

claudedo start now runs a mic check first (warm-up + brief capture, aborts with
guidance if silent; --skip-audio-check to bypass) then drops into a visible
listen loop printing the recognition/action log: a startup banner, then
heard -> matched -> target / injected per utterance, target/mode state changes,
and (listen mode) non-wake speech dropped WITHOUT the transcript per the privacy
invariant.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 19:30:36 -04:00
eb587692e1 fix: prime mic to skip RDPSource resume gap
WSLg's RDPSource suspends when idle and emits ~1-2s of silence while it resumes
on the first read, so a short timed capture (test-audio) or the first utterance
after daemon start could be lost. add audio.warm_up() that opens a stream and
reads until a non-silent block arrives (or times out); call it at daemon startup
and before test-audio's capture. test-audio now primes then captures 3s.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 19:09:08 -04:00
84c74603e5 feat: output-handler seam with tmux and stdout handlers
extract an OutputHandler abstract base; TmuxOutputHandler is production
(send-keys, PTY-only), StdoutOutputHandler prints what would be injected so
grammar+keymap run end-to-end without a live claude session (the deterministic
test path). module-level shims default to tmux so the daemon is unchanged.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 18:42:34 -04:00
d43004e4b9 feat: tmux send-keys settings in install.sh bootstrap
append escape-time 0, large history-limit, allow-passthrough, and extended-keys
to ~/.tmux.conf under an idempotent marker block (no clobber). required for
reliable keystroke injection and for notifications/modified-keys to reach the
claude pane.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 18:42:26 -04:00
66b08d290c docs: lead how-to-run with the terminal-run model
state terminal-run as the product (the claudedo start terminal is the
recognition/action console) and frame backgrounding/autostart/systemd as
optional extras, not the default.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 18:42:22 -04:00
7f4a6f6699 style: drop inline comments, trim docstring periods
remove inline comments (CLAUDE.md: docstrings only), strip trailing periods
from single-line docstrings, and fix a PulseArmy->PulseAudio typo. no behavior
change.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 18:42:17 -04:00
bf516143b5 install: shell cc kit, opt-in autostart, bootstrap
cc kit as a sourced ~/.config/claudedo/cc.sh (bash+zsh, forced explicit names).
opt-in rc autostart guarded by CLAUDEDO_AUTOSTART + an optional systemd user
unit. install.sh is idempotent: WSL audio deps, ~/.asoundrc pulse shim, audio
verify, model prime, and source-line rc wiring with backups.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 17:55:30 -04:00
7780a8d47c daemon: capture->stt->match->inject loop and CLI
daemon.py runs the loop with pidfile/state, runtime mode switching, and the
privacy invariant: in listen mode any non-wake utterance is dropped the instant
grammar.parse() returns None. __main__.py exposes start|stop|status|test-audio|
install|switch.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 17:55:25 -04:00
947b30c22e grammar: fuzzy wake gate and command matching
word-boundary wake stripping that's lenient on the coined word 'claudedo'
(despaced-prefix match) without swallowing the command's spaces. data-driven
phrase->action map; number words normalized to digits; 'target' aliases
'switch'.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 17:55:21 -04:00
da7c39c4f2 audio: local STT and mic capture
stt.py wraps faster-whisper for fully on-device transcription. audio.py
captures via sounddevice with two paths: silence-segmented for listen mode
and held-key for ptt. resolves the input device from config (auto/index/name).

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 17:55:17 -04:00
732bad4c8d core: confirmed keymap, tmux injection, session targeting
keys.py is the single source of truth for claude code's prompt keystrokes,
confirmed empirically against a live v2.1.191 session: bare digits select-
and-confirm immediately (no trailing enter). inject.py only ever calls
tmux send-keys (PTY injection, never OS input). target.py resolves the
active session from ~/.claude-active with a has-session guard and a single
session_name() mapping (claude-<name>) shared with the cc kit.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 17:55:13 -04:00
c61eb85748 config: typed config loader and config.toml
load/validate config.toml with clear errors; defaults to listen mode and
the 'small' whisper model. all tunables (wake phrases, audio thresholds,
type_autosend) live here, no hardcoded paths or secrets in code.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 17:55:08 -04:00
b6d8683e39 build: pip packaging and package init
src/ layout, console entry point 'claudedo', python 3.10+ deps
(sounddevice, numpy, faster-whisper, tomli backport).

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 17:55:01 -04:00
98a6f0283f init: claude, with ears
Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 17:54:49 -04:00