Commit Graph

15 Commits

Author SHA1 Message Date
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