feat(cli): stdin support, download progress, bash completion, thread-safe defaults#11
Merged
Merged
Conversation
…safe defaults Four small quality-of-life improvements bundled into one PR: - cli: read text from piped stdin when --file and the positional are absent. `echo hi | stackvox` defaults to speak. _read_text picks --file > positional > stdin in that order. - engine: print percentage updates to stderr while downloading the ~340 MB Kokoro model on first run, so it doesn't look like a hang. Uses urlretrieve's reporthook callback — no new deps. - cli: new `stackvox completion bash` subcommand emits a static bash completion script. Source via eval or persist to a file under ~/.bashrc. Voice list isn't auto-completed (would require loading the model on every TAB); subcommands and most flags are. - engine: wrap _get_default in double-checked locking. Without it, concurrent first calls to the module-level speak()/synthesize() could race and instantiate two Stackvox engines, each loading the model. Tests: stdin precedence, piped-stdin shortcut, completion script emission. New autouse fixture defaults stdin to a TTY so existing tests aren't perturbed by the new shortcut. README CLI section updated with stdin example and completion install snippet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Apr 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Four small quality-of-life CLI/engine improvements from the post-v0.2.0 audit. None change existing behavior; all are purely additive.
Changes
`feat`: read text from piped stdin
`echo hi | stackvox` now works (previously printed help). `_read_text` picks `--file` > positional > piped stdin, in that order. Existing patterns (positional text, `--file`) are unchanged.
`feat`: progress on first-run model download
The ~340 MB Kokoro model used to download silently — looked like a hang on slow networks. Now prints a percentage line to stderr via `urlretrieve`'s `reporthook`. No new dependencies; `tqdm` would have been heavier than the value added.
`feat`: bash completion via `stackvox completion bash`
```bash
eval "$(stackvox completion bash)" # current shell
or persist:
stackvox completion bash > ~/.stackvox-completion.bash
echo 'source ~/.stackvox-completion.bash' >> ~/.bashrc
```
Static script — completes subcommands, common flags, and file paths for `--file` / `--out`. Voice list isn't auto-completed because that would require loading the model on every TAB. zsh/fish can be added later if asked for.
`fix`: thread-safe `_default` Stackvox singleton
`_get_default()` previously had a TOCTOU race: two threads concurrently calling the module-level `speak()` / `synthesize()` at process start could both see `_default is None` and each instantiate a `Stackvox` (each loading the 340 MB model). Now wrapped in double-checked locking — fast path stays lock-free after init.
Tests
`pytest`: 17/17 passing locally. `ruff check`, `ruff format --check`, `mypy` all clean.
Test plan
Summary by cubic
Adds stdin piping, visible first-run model download progress, and Bash completion to the
stackvoxCLI, plus a thread-safe default engine to prevent duplicate model loads.New Features
echo "hi" | stackvoxnow works; text precedence is--file > positional > stdin.stackvox completion bashemits a static script that completes subcommands, common flags, and file paths.Bug Fixes
_get_default()thread-safe with double-checked locking to avoid creating multipleStackvoxinstances under concurrent first calls.Written for commit 1a56141. Summary will update on new commits. Review in cubic