vocalize-cli 0.11.0__tar.gz → 0.13.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/CHANGELOG.md +172 -0
- vocalize_cli-0.11.0/README.md → vocalize_cli-0.13.0/PKG-INFO +174 -60
- vocalize_cli-0.11.0/PKG-INFO → vocalize_cli-0.13.0/README.md +138 -96
- vocalize_cli-0.13.0/docs/app.md +205 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/dictation.md +66 -16
- vocalize_cli-0.13.0/docs/installation.md +211 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/choreography.md +110 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/decisions.md +509 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/design.md +355 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/plan.md +331 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/review-0.12.0.md +142 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/review-0.13.0.md +252 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/review-plan-2026-09-06.md +41 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-1-local-first-defaults/project-plan.md +76 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-1-local-first-defaults/report.md +16 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-1-local-first-defaults/task-report.md +30 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-1-local-first-defaults/validate-exit.sh +134 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-10-release-0-13-0/project-plan.md +50 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-10-release-0-13-0/validate-exit.sh +124 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-11-cue-hold-paste/project-plan.md +52 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-11-cue-hold-paste/validate-exit.sh +125 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-11b-playback-pause/project-plan.md +54 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-11b-playback-pause/validate-exit.sh +128 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-12-release-0-13-1/project-plan.md +47 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-12-release-0-13-1/validate-exit.sh +122 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-13-spikes/project-plan.md +45 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-13-spikes/validate-exit.sh +114 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-14-local-llm/project-plan.md +50 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-14-local-llm/validate-exit.sh +124 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-15-notes/project-plan.md +48 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-15-notes/validate-exit.sh +111 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-15b-recording-pause/project-plan.md +57 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-15b-recording-pause/validate-exit.sh +131 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-16-release-0-14-0/project-plan.md +50 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-16-release-0-14-0/validate-exit.sh +124 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-17-optional-spikes/project-plan.md +44 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-17-optional-spikes/validate-exit.sh +118 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-2-stt-decoding/project-plan.md +49 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-2-stt-decoding/report.md +16 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-2-stt-decoding/task-report.md +35 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-2-stt-decoding/validate-exit.sh +113 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-3-llm-and-enums/project-plan.md +55 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-3-llm-and-enums/report.md +20 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-3-llm-and-enums/task-report.md +36 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-3-llm-and-enums/validate-exit.sh +152 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-4-keychain/project-plan.md +80 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-4-keychain/report.md +16 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-4-keychain/task-report.md +34 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-4-keychain/validate-exit.sh +134 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-5-keys-tab/project-plan.md +47 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-5-keys-tab/report.md +24 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-5-keys-tab/task-report.md +31 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-5-keys-tab/validate-exit.sh +118 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-6-release-0-12-0/project-plan.md +50 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-6-release-0-12-0/report.md +31 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-6-release-0-12-0/validate-exit.sh +124 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-7-hotkey-spike-and-builder/project-plan.md +45 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-7-hotkey-spike-and-builder/report.md +17 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-7-hotkey-spike-and-builder/task-report.md +31 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-7-hotkey-spike-and-builder/validate-exit.sh +113 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-8a-app-swift/project-plan.md +44 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-8a-app-swift/report.md +19 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-8a-app-swift/task-report.md +30 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-8a-app-swift/validate-exit.sh +124 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-8b-app-python/project-plan.md +49 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-8b-app-python/report.md +20 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-8b-app-python/task-report.md +36 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-8b-app-python/validate-exit.sh +119 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-9-doctor-integrate-setup/project-plan.md +48 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-9-doctor-integrate-setup/report.md +21 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-9-doctor-integrate-setup/task-report.md +29 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/run-9-doctor-integrate-setup/validate-exit.sh +121 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/spike-notes.md +47 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/split-assessment.md +57 -0
- vocalize_cli-0.13.0/docs/plans/2026-09-app-roadmap/verification.md +216 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-10-release-0-11-0/report.md +8 -1
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/provider-credentials.md +72 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/roadmap.md +2 -1
- vocalize_cli-0.13.0/hooks/install_quick_action.py +13 -0
- vocalize_cli-0.13.0/hooks/speak_options.py +13 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/pyproject.toml +2 -2
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/conftest.py +76 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/portal_page_harness.js +222 -2
- vocalize_cli-0.13.0/tests/test_app_build.py +242 -0
- vocalize_cli-0.13.0/tests/test_app_cli.py +777 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_auth.py +206 -1
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_chain.py +39 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_cli.py +380 -6
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_config.py +281 -7
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_dictate.py +206 -114
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_http.py +19 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_install_quick_action.py +70 -30
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_listen_check.py +3 -2
- vocalize_cli-0.13.0/tests/test_llm.py +491 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_local_install.py +31 -8
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_portal.py +440 -3
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_portal_assets.py +30 -6
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_readiness.py +396 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_recorder_build.py +1 -37
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_speak_options.py +14 -1
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_whisper_manifest.py +22 -5
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_whisper_worker.py +73 -2
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_wizard.py +44 -2
- vocalize_cli-0.13.0/uv.lock +1571 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/__init__.py +2 -2
- vocalize_cli-0.13.0/vocalize/app.py +406 -0
- vocalize_cli-0.13.0/vocalize/assets/claude/speak/SKILL.md +168 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/assets/portal.html +9 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/assets/portal.js +265 -29
- {vocalize_cli-0.11.0/hooks → vocalize_cli-0.13.0/vocalize/assets}/quick_actions/Speak Latest Plan.workflow/Contents/Resources/document.wflow +1 -1
- {vocalize_cli-0.11.0/hooks → vocalize_cli-0.13.0/vocalize/assets}/quick_actions/Speak with Vocalize.workflow/Contents/Resources/document.wflow +2 -2
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/auth.py +184 -8
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/chain.py +21 -1
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/cli.py +327 -31
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/config.py +299 -10
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/dictate.py +71 -79
- vocalize_cli-0.13.0/vocalize/integrate.py +264 -0
- vocalize_cli-0.13.0/vocalize/llm.py +315 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/local/install.py +172 -52
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/local/whisper_manifest.py +11 -2
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/local/whisper_worker.py +39 -2
- vocalize_cli-0.13.0/vocalize/menubar/Info.plist.in +47 -0
- vocalize_cli-0.13.0/vocalize/menubar/VocalizeApp.swift +1560 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/portal.py +160 -11
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/providers/_http.py +9 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/providers/kokoro.py +2 -1
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/readiness.py +232 -3
- {vocalize_cli-0.11.0/hooks → vocalize_cli-0.13.0/vocalize}/speak_options.py +4 -1
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/wizard.py +9 -1
- vocalize_cli-0.11.0/docs/installation.md +0 -483
- vocalize_cli-0.11.0/hooks/install_quick_action.py +0 -136
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/.env.example +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/.github/workflows/ci.yml +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/.gitignore +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/LICENSE +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/next-features-analysis.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/choreography.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/decisions.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/design.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/review-0.10.0.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/review-0.11.0.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-1-status/project-plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-1-status/report.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-1-status/validate-exit.sh +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-10-release-0-11-0/project-plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-10-release-0-11-0/validate-exit.sh +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-2-stt-runtime/project-plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-2-stt-runtime/report.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-2-stt-runtime/validate-exit.sh +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-3-recorder/project-plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-3-recorder/report.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-3-recorder/validate-exit.sh +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-4-dictation/project-plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-4-dictation/report.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-4-dictation/validate-exit.sh +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-5-resume/project-plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-5-resume/report.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-5-resume/validate-exit.sh +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-6-release-0-10-0/project-plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-6-release-0-10-0/report.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-6-release-0-10-0/validate-exit.sh +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-7-portal-read/project-plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-7-portal-read/report.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-7-portal-read/review-findings.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-7-portal-read/validate-exit.sh +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-8-portal-write/project-plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-8-portal-write/report.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-8-portal-write/validate-exit.sh +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-9-portal-page/project-plan.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-9-portal-page/report.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-9-portal-page/review-findings.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/run-9-portal-page/validate-exit.sh +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/spike-2026-09-01.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/split-assessment.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/plans/2026-09-next-features/verification.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/research/2026-09-01-config-portal-design.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/research/2026-09-01-dictation-design.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/research/2026-09-01-voicebox-findings.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/docs/research/2026-09-04-app-roadmap-analysis.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/hooks/claude_stop_hook.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/hooks/install_hook.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/hooks/speak_url_gate.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_audio.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_cache.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_claude_stop_hook.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_clipboard.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_cue_assets.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_elevenlabs_provider.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_exceptions.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_google_provider.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_install_hook.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_kokoro_manifest.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_kokoro_provider.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_kokoro_worker.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_ledger.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_openai_provider.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_polly_provider.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_preprocess.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_providers_registry.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_say_provider.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_speak_url_gate.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_tts.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/tests/test_uv_path.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/__main__.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/assets/cues/README.md +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/assets/cues/ready.wav +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/assets/cues/start.wav +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/assets/cues/stopped.wav +0 -0
- {vocalize_cli-0.11.0/hooks → vocalize_cli-0.13.0/vocalize/assets}/quick_actions/Dictate with Vocalize.workflow/Contents/Info.plist +0 -0
- {vocalize_cli-0.11.0/hooks → vocalize_cli-0.13.0/vocalize/assets}/quick_actions/Dictate with Vocalize.workflow/Contents/Resources/document.wflow +0 -0
- {vocalize_cli-0.11.0/hooks → vocalize_cli-0.13.0/vocalize/assets}/quick_actions/Speak Latest Plan.workflow/Contents/Info.plist +0 -0
- {vocalize_cli-0.11.0/hooks → vocalize_cli-0.13.0/vocalize/assets}/quick_actions/Speak with Vocalize.workflow/Contents/Info.plist +0 -0
- {vocalize_cli-0.11.0/hooks → vocalize_cli-0.13.0/vocalize/assets}/quick_actions/Stop Vocalize.workflow/Contents/Info.plist +0 -0
- {vocalize_cli-0.11.0/hooks → vocalize_cli-0.13.0/vocalize/assets}/quick_actions/Stop Vocalize.workflow/Contents/Resources/document.wflow +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/audio.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/cache.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/clipboard.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/exceptions.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/interrupted.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/ledger.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/local/__init__.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/local/kokoro_manifest.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/local/kokoro_worker.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/preprocess.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/providers/__init__.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/providers/elevenlabs.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/providers/google.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/providers/openai.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/providers/polly.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/providers/say.py +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/recorder/Info.plist.in +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/recorder/Recorder.entitlements +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/recorder/VocalizeRecorder.swift +0 -0
- {vocalize_cli-0.11.0 → vocalize_cli-0.13.0}/vocalize/tts.py +0 -0
|
@@ -3,6 +3,178 @@
|
|
|
3
3
|
All notable changes to this project are documented here. Format follows
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
5
|
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
Nothing yet.
|
|
9
|
+
|
|
10
|
+
## 0.13.0 - 2026-09-08
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **The `[app]` config table** for the menu-bar app that arrives in 0.13.0:
|
|
15
|
+
`dictate`, `speak` and `stop` chords (`ctrl+alt+cmd+d`, `+s`, `+x` by
|
|
16
|
+
default; tokens joined by `+`, modifiers ctrl/alt/cmd/shift with their
|
|
17
|
+
long-form aliases, a key of a–z, 0–9 or f1–f12, ctrl or cmd required,
|
|
18
|
+
`""` disables) and `dictate_mode` (`toggle`; `hold` parses and resolves
|
|
19
|
+
to toggle with one warning until 0.13.1). The wizard renders it and
|
|
20
|
+
`vocalize settings` prints `app.<key>=…` in one canonical spelling.
|
|
21
|
+
- **`vocalize app install / uninstall / status [--json] / restart`** —
|
|
22
|
+
a menu-bar app (`Vocalize.app`) that owns the dictation, speak and stop
|
|
23
|
+
hotkeys system-wide, as a LaunchAgent, so a hotkey works from any app
|
|
24
|
+
with no Services menu and no per-app shortcut assignment. `install`
|
|
25
|
+
builds the bundle, warns about a running Hammerspoon or a Services
|
|
26
|
+
shortcut assigned to the "Dictate with Vocalize" Quick Action, resets
|
|
27
|
+
the Accessibility grant
|
|
28
|
+
only on a rebuild, and loads the LaunchAgent; `status` reports what's
|
|
29
|
+
built, whether the agent is loaded, and the app's own hotkey and
|
|
30
|
+
Accessibility state; `restart` kicks the running app without touching
|
|
31
|
+
the LaunchAgent; `uninstall` removes everything `install` put down
|
|
32
|
+
and leaves the Accessibility entry in System Settings alone. See
|
|
33
|
+
[docs/app.md](docs/app.md).
|
|
34
|
+
- **`dictate.session` gains a `state` and a per-dictation `nonce`.**
|
|
35
|
+
`state` moves through `starting` → `recording` → `transcribing` as a
|
|
36
|
+
dictation runs, so anything reading the session file (the app included)
|
|
37
|
+
knows which stage it's watching, not just that one is in progress.
|
|
38
|
+
`nonce` ties one dictation's session to its eventual `dictate.copied`
|
|
39
|
+
write. Unknown keys in the file are still ignored.
|
|
40
|
+
- **`vocalize doctor [--json]`** — every readiness row plus the toolchain
|
|
41
|
+
and environment checks `status` doesn't cover: `cli path`, `uv`,
|
|
42
|
+
`swiftc`, `claude` on PATH, the running console script's shebang
|
|
43
|
+
(brew rot), a Hammerspoon or old Quick Action conflict, `vocalize
|
|
44
|
+
--version` cold-start time, app bundle state with its repair command,
|
|
45
|
+
and the notes folder's size on disk. Exits 1 only on a failing row;
|
|
46
|
+
warn rows print but don't fail a script.
|
|
47
|
+
- **`vocalize integrate claude [--yes]`** — one command in place of the
|
|
48
|
+
hand-rolled `/speak` skill and the standalone Quick Action installer.
|
|
49
|
+
Checks `vocalize`, `claude`, `node`, and `python3` on PATH, installs
|
|
50
|
+
`~/.claude/skills/speak/SKILL.md` from the package (kept unless
|
|
51
|
+
`--yes`), installs the four Quick Actions into `~/Library/Services`,
|
|
52
|
+
and prints the GUI-only hotkey and Accessibility steps. The Quick
|
|
53
|
+
Action installer and its `.workflow` bundles moved into the package
|
|
54
|
+
(`vocalize/assets/quick_actions/`); `hooks/install_quick_action.py` is
|
|
55
|
+
now a thin wrapper around it. The baked `claude` path is the stable
|
|
56
|
+
symlink, not `.resolve()`'s version-pinned Caskroom target, so a
|
|
57
|
+
`brew upgrade claude-code` no longer silently breaks the summary
|
|
58
|
+
picker.
|
|
59
|
+
- **The Setup tab** in `vocalize portal` — a nine-step checklist
|
|
60
|
+
(toolchain, both bundles, login item, chords, model download,
|
|
61
|
+
microphone, `/speak` and Quick Actions, Accessibility, self-test)
|
|
62
|
+
built from the readiness rows the sidebar shows; its first step points at
|
|
63
|
+
`vocalize doctor`. Its install
|
|
64
|
+
buttons drive the existing `/api/local/install` routes, now including
|
|
65
|
+
target `app`. See [docs/app.md](docs/app.md#the-setup-tab).
|
|
66
|
+
|
|
67
|
+
### Changed
|
|
68
|
+
|
|
69
|
+
- **The recorder is built by a general bundle builder.** `build_bundle(BundleSpec)`
|
|
70
|
+
replaces the recorder-only code path; `build_recorder` is the recorder's
|
|
71
|
+
door onto it and its build is unchanged byte for byte (a golden test pins
|
|
72
|
+
the `swiftc` and `codesign` argv, because any drift is a new ad-hoc
|
|
73
|
+
signature and a microphone re-grant). `vocalize local uninstall --stt`
|
|
74
|
+
now removes only the recorder bundle and its stamp, never the whole
|
|
75
|
+
`~/.cache/vocalize/bin`.
|
|
76
|
+
- **`vocalize clip` exits 3, not 1, when it refuses a credential-shaped
|
|
77
|
+
clipboard.** A script that already treats exit 1 as "something went
|
|
78
|
+
wrong, try again" can now tell that refusal apart from a real failure.
|
|
79
|
+
|
|
80
|
+
## 0.12.0 - 2026-09-07
|
|
81
|
+
|
|
82
|
+
### Changed
|
|
83
|
+
|
|
84
|
+
- **The default chain is now `kokoro`, then `say`.** A config with no
|
|
85
|
+
`chain` used to try ElevenLabs first; it now tries the on-device voice
|
|
86
|
+
first and falls back to macOS `say`. When `say` speaks because the Kokoro
|
|
87
|
+
model was never installed, the fallback line says so once and names the
|
|
88
|
+
fix: `vocalize local install`. Users who never set a chain hear `say`
|
|
89
|
+
after upgrading until they run that install; anyone with an explicit
|
|
90
|
+
`chain` sees no change. `vocalize usage`, `vocalize status` and the portal
|
|
91
|
+
now list the local providers first.
|
|
92
|
+
- **Dictation decodes with beam search.** whisper.cpp ran with its greedy
|
|
93
|
+
decoder, which merged words on fast speech ("toget" for "to get",
|
|
94
|
+
[#4](https://github.com/matthager12-collab/vocalize/issues/4)). The worker
|
|
95
|
+
now uses beam search with five beams, whisper.cpp's own default for that
|
|
96
|
+
strategy. `[stt] beam_size` (1–8) is the escape hatch: `1` restores the
|
|
97
|
+
greedy decoder if a take is slow to land on your machine. Honest result:
|
|
98
|
+
on the owner's own voice both decoders still produced "themerge" for
|
|
99
|
+
"the merge", so beam search improves decoding but does not close #4;
|
|
100
|
+
that issue stays open. The cost was measured on a 43 s synthetic clip
|
|
101
|
+
and recorded in `docs/plans/2026-09-app-roadmap/spike-notes.md`.
|
|
102
|
+
|
|
103
|
+
- **The default dictation model is now `large-v3-turbo-q5_0`.** On the
|
|
104
|
+
owner's own voice it was the first model to keep "the merge" as two
|
|
105
|
+
words ([#4](https://github.com/matthager12-collab/vocalize/issues/4));
|
|
106
|
+
beam search alone did not. It is no slower than `small.en` on an M4 and
|
|
107
|
+
uses about 90 MB more. **Upgrade note:** if your `[stt]` table sets no
|
|
108
|
+
`model`, dictation looks for the new default — run
|
|
109
|
+
`vocalize local install --stt` once (547 MB), or set
|
|
110
|
+
`model = "small.en"` to keep the lighter model.
|
|
111
|
+
- **`[stt] cleanup` names where the cleanup pass runs.** It was `true` or
|
|
112
|
+
`false`; it is now `off`, `claude-cli`, `anthropic` or `local` (`local`
|
|
113
|
+
is accepted today and honoured from 0.14.0). Older `true` / `false`
|
|
114
|
+
values keep working. The pass lives in a new `vocalize/llm.py`, one seam
|
|
115
|
+
for every language-model call, and the default prompt now also drops
|
|
116
|
+
restatements, false starts and filler
|
|
117
|
+
([#3](https://github.com/matthager12-collab/vocalize/issues/3)); say
|
|
118
|
+
"verbatim" as the first word of a take, pass `--verbatim`, or set
|
|
119
|
+
`[stt] verbatim = true` to keep every word.
|
|
120
|
+
- **Every cloud send is visible.** One stderr line, `vocalize: sent to
|
|
121
|
+
<backend>`, prints immediately before text leaves the machine and never
|
|
122
|
+
otherwise; the clipboard notification for a cleaned take says "cleaned
|
|
123
|
+
up by Claude — sent off this Mac".
|
|
124
|
+
- **`claude -p` sessions are tighter.** The cleanup pass and the plan-
|
|
125
|
+
speaking hook now pass `--strict-mcp-config`, run from the system
|
|
126
|
+
temporary directory, and the cleanup pass excludes your own hooks,
|
|
127
|
+
skills and `CLAUDE.md` (`--setting-sources ""`) and strips any stored
|
|
128
|
+
Anthropic key from the child's environment.
|
|
129
|
+
- **Provider settings are type-checked** (issue
|
|
130
|
+
[#5](https://github.com/matthager12-collab/vocalize/issues/5)): a
|
|
131
|
+
`voice`, `model`, `engine`, `language`, `region` or `profile` that is not
|
|
132
|
+
a short printable string is refused with a message naming the file and
|
|
133
|
+
the key, in the CLI and the portal alike.
|
|
134
|
+
- **Sentences no longer run together with the turbo models.** Their
|
|
135
|
+
segments arrive without a leading space and the worker joined them with
|
|
136
|
+
nothing ("working.I want"); segments are now joined with one space.
|
|
137
|
+
|
|
138
|
+
### Fixed
|
|
139
|
+
|
|
140
|
+
- **A stored key is readable from every Python on the Mac.** macOS pins a
|
|
141
|
+
keychain item to the binary that created it, so a key stored from the
|
|
142
|
+
terminal could be invisible, or behind an "Allow" dialog, when Claude
|
|
143
|
+
Code's shell or an upgraded vocalize asked for it. Keys are now written
|
|
144
|
+
and read through Apple's own `security` tool (secret on stdin, never on a
|
|
145
|
+
command line), which is the same accessing application whatever spawned
|
|
146
|
+
it; the item also records the date the key was last validated, shown by
|
|
147
|
+
`vocalize auth status`. An older item is replaced in place on the next
|
|
148
|
+
`vocalize auth login`.
|
|
149
|
+
|
|
150
|
+
### Added
|
|
151
|
+
|
|
152
|
+
- **An Anthropic key slot, and a Keys tab that can test and remove.**
|
|
153
|
+
`vocalize auth login --provider anthropic` stores the key the `anthropic`
|
|
154
|
+
cleanup backend uses, under its own keychain item; `auth status`,
|
|
155
|
+
`auth logout` and `vocalize usage` know the slot too. It is a key, not a
|
|
156
|
+
voice: the chain does not accept it. On the portal's Keys tab every slot
|
|
157
|
+
(the three voice providers and Anthropic) gets **Test without storing**,
|
|
158
|
+
which checks a key and keeps nothing, and **Remove stored key**, which
|
|
159
|
+
reads the keychain back before it says the key is gone; each card shows
|
|
160
|
+
when its key was last checked. The key field is `autocomplete=
|
|
161
|
+
"new-password"`, the value Safari and Chrome honour on a password field.
|
|
162
|
+
The Local tab gained a select for the cleanup backend.
|
|
163
|
+
|
|
164
|
+
- **An Anthropic API backend for the cleanup pass** (`[stt] cleanup =
|
|
165
|
+
"anthropic"`): one Messages API call with a key from `ANTHROPIC_API_KEY`
|
|
166
|
+
or the keychain slot `anthropic-api-key`, under a monthly character
|
|
167
|
+
budget (`[providers.anthropic] monthly_chars`, 2,000,000 when unset)
|
|
168
|
+
counted in the usage ledger. The key is stored from the CLI or the
|
|
169
|
+
portal's Keys tab, as described above.
|
|
170
|
+
- **A `[notes]` config table** (`folder`, `template`, `summarizer`,
|
|
171
|
+
`keep_audio`, `model`) is parsed, validated and preserved by every writer
|
|
172
|
+
of the config file. `vocalize notes` itself arrives in 0.14.0.
|
|
173
|
+
- **`large-v3-turbo-q8_0`** joins the dictation models: the same turbo model
|
|
174
|
+
as `q5_0` with 8-bit weights (834 MB on disk), for machines with 16 GB or
|
|
175
|
+
more. `vocalize local install --stt --model large-v3-turbo-q8_0`. Pinned
|
|
176
|
+
from a completed download like the other three.
|
|
177
|
+
|
|
6
178
|
## 0.11.0 - 2026-09-05
|
|
7
179
|
|
|
8
180
|
### Added
|
|
@@ -1,11 +1,48 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: vocalize-cli
|
|
3
|
+
Version: 0.13.0
|
|
4
|
+
Summary: A local-first CLI that turns text, markdown, or piped stdin into speech: the on-device Kokoro voice by default, cloud voices optional, with markdown-table-aware preprocessing and Claude Code hooks.
|
|
5
|
+
Project-URL: Homepage, https://github.com/matthager12-collab/vocalize
|
|
6
|
+
Project-URL: Repository, https://github.com/matthager12-collab/vocalize
|
|
7
|
+
Author: Mat
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: claude-code,cli,elevenlabs,kokoro,local,markdown,text-to-speech
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: click>=8.1
|
|
22
|
+
Requires-Dist: elevenlabs>=2.0
|
|
23
|
+
Requires-Dist: keyring>=25
|
|
24
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: build; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
30
|
+
Requires-Dist: twine; extra == 'dev'
|
|
31
|
+
Provides-Extra: dotenv
|
|
32
|
+
Requires-Dist: python-dotenv>=1.0; extra == 'dotenv'
|
|
33
|
+
Provides-Extra: polly
|
|
34
|
+
Requires-Dist: boto3>=1.34; extra == 'polly'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
1
37
|
# vocalize
|
|
2
38
|
|
|
3
39
|
[](https://github.com/matthager12-collab/vocalize/actions/workflows/ci.yml)
|
|
4
40
|
|
|
5
41
|
A command-line tool that turns text, markdown files, or piped stdin into
|
|
6
|
-
natural-sounding speech
|
|
7
|
-
plus a hook that wires it directly into
|
|
8
|
-
so Claude's responses get read
|
|
42
|
+
natural-sounding speech on your own machine by default, with cloud voices as
|
|
43
|
+
an option — plus a hook that wires it directly into
|
|
44
|
+
[Claude Code](https://claude.com/claude-code), so Claude's responses get read
|
|
45
|
+
aloud in your terminal or IDE.
|
|
9
46
|
|
|
10
47
|
## Quickstart
|
|
11
48
|
|
|
@@ -14,17 +51,19 @@ pipx install vocalize-cli
|
|
|
14
51
|
```
|
|
15
52
|
|
|
16
53
|
```bash
|
|
17
|
-
vocalize
|
|
54
|
+
vocalize local install
|
|
18
55
|
```
|
|
19
56
|
|
|
20
|
-
|
|
57
|
+
Downloads the on-device Kokoro voice once (about 350 MB; needs
|
|
58
|
+
[`uv`](https://docs.astral.sh/uv/)). Skip it and `vocalize` speaks through
|
|
59
|
+
macOS `say` until you come back to it — the fallback line tells you so.
|
|
21
60
|
|
|
22
61
|
```bash
|
|
23
62
|
vocalize speak "hello"
|
|
24
63
|
```
|
|
25
64
|
|
|
26
|
-
|
|
27
|
-
|
|
65
|
+
Prefer a cloud voice? See [Providers and fallback](#providers-and-fallback):
|
|
66
|
+
`vocalize config` walks you through a key, a voice and a speed.
|
|
28
67
|
|
|
29
68
|
## Why this exists
|
|
30
69
|
|
|
@@ -62,33 +101,8 @@ cd vocalize
|
|
|
62
101
|
pip install -e .
|
|
63
102
|
```
|
|
64
103
|
|
|
65
|
-
|
|
66
|
-
[
|
|
67
|
-
(free tier: 10,000 characters/month, API access included, no commercial
|
|
68
|
-
license). Then, recommended, store it in your OS keychain:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
vocalize auth login
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
This prompts for the key (input hidden), validates it against the
|
|
75
|
-
ElevenLabs API, and stores it via your OS's own keychain (macOS Keychain,
|
|
76
|
-
Windows Credential Locker, Linux Secret Service) — no plaintext file to
|
|
77
|
-
manage. Piping it in from a secret manager works too:
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
op read op://vault/elevenlabs/key | vocalize auth login --stdin
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
An environment variable or `.env` file work as well, and take priority over
|
|
84
|
-
the keychain if both are set:
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
export ELEVENLABS_API_KEY=your-key-here
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
or copy `.env.example` to `.env` and fill it in (requires the optional
|
|
91
|
-
`python-dotenv` extra: `pip install -e ".[dotenv]"`).
|
|
104
|
+
Cloud voices need an API key; storing one is covered under
|
|
105
|
+
[Providers and fallback](#providers-and-fallback).
|
|
92
106
|
|
|
93
107
|
## Usage
|
|
94
108
|
|
|
@@ -206,7 +220,8 @@ back to `~/.config/vocalize/config.toml`. Flat keys, no sections:
|
|
|
206
220
|
```toml
|
|
207
221
|
chain = ["elevenlabs", "google", "say"]
|
|
208
222
|
|
|
209
|
-
# Flat keys
|
|
223
|
+
# Flat keys are the original cloud voice's settings, unchanged since
|
|
224
|
+
# before there was a chain; see Providers and fallback.
|
|
210
225
|
voice = "21m00Tcm4TlvDq8ikWAM"
|
|
211
226
|
model = "eleven_flash_v2_5"
|
|
212
227
|
speed = 0.95
|
|
@@ -278,8 +293,10 @@ Five tabs:
|
|
|
278
293
|
- **Chain** — reorder providers, or add and remove one.
|
|
279
294
|
- **Providers** — each provider's voice, model, speed, and monthly budget,
|
|
280
295
|
with a live preview of the voice you're looking at.
|
|
281
|
-
- **Keys** — store or
|
|
282
|
-
|
|
296
|
+
- **Keys** — store, test or remove an API key for each provider and for
|
|
297
|
+
Anthropic (the dictation cleanup backend, not a voice); the field is
|
|
298
|
+
masked and never offers to autocomplete, a stored key is never shown
|
|
299
|
+
again, and each card says when the key was last checked.
|
|
283
300
|
- **Usage** — this month's spend and quota per provider.
|
|
284
301
|
- **Local** — install or update the on-device Kokoro and whisper models,
|
|
285
302
|
with progress.
|
|
@@ -358,6 +375,41 @@ For the click-by-click setup of each provider — where to go, what to click,
|
|
|
358
375
|
the one command that stores the credential, the one command that proves it
|
|
359
376
|
works — see [docs/provider-credentials.md](docs/provider-credentials.md).
|
|
360
377
|
|
|
378
|
+
### Storing a cloud API key
|
|
379
|
+
|
|
380
|
+
For ElevenLabs, get a free API key at
|
|
381
|
+
[elevenlabs.io/app/settings/api-keys](https://elevenlabs.io/app/settings/api-keys)
|
|
382
|
+
(free tier: 10,000 characters/month, API access included, no commercial
|
|
383
|
+
license). Then, recommended, store it in your OS keychain:
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
vocalize auth login
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
This prompts for the key (input hidden), validates it against the
|
|
390
|
+
ElevenLabs API, and stores it via your OS's own keychain (macOS Keychain,
|
|
391
|
+
Windows Credential Locker, Linux Secret Service) — no plaintext file to
|
|
392
|
+
manage. On macOS the item is written and read through Apple's own
|
|
393
|
+
`security` tool, so the same key is readable from every Python and app
|
|
394
|
+
that runs vocalize — your terminal, Claude Code's shell, the portal —
|
|
395
|
+
with no keychain dialog, and `vocalize auth status` shows the date it was
|
|
396
|
+
last validated. Piping it in from a secret manager works too:
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
op read op://vault/elevenlabs/key | vocalize auth login --stdin
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
An environment variable or `.env` file work as well, and take priority over
|
|
403
|
+
the keychain if both are set:
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
export ELEVENLABS_API_KEY=your-key-here
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
or copy `.env.example` to `.env` and fill it in (requires the optional
|
|
410
|
+
`python-dotenv` extra: `pip install -e ".[dotenv]"`).
|
|
411
|
+
|
|
412
|
+
|
|
361
413
|
## Budgets and the usage ledger
|
|
362
414
|
|
|
363
415
|
Cloud providers don't stop at their free tier — they bill past it. vocalize
|
|
@@ -421,7 +473,8 @@ Use it for one read with `--provider kokoro`, or add it to your chain in
|
|
|
421
473
|
Long text streams: it's broken into ~400-character pieces, and playback
|
|
422
474
|
starts after the first one is ready — roughly 20–25 seconds of speech —
|
|
423
475
|
instead of waiting for the whole thing to render. Measured on this Mac
|
|
424
|
-
(M3): about 5x faster than real time, peaking around
|
|
476
|
+
(M3): about 5x faster than real time, peaking around 760 MB of RAM (measured
|
|
477
|
+
on an M4 on 2026-09-07; the M3 spike saw 870 MB) while
|
|
425
478
|
rendering. `vocalize stop`, run from any terminal, halts a Kokoro read
|
|
426
479
|
mid-sentence the same as any other provider.
|
|
427
480
|
|
|
@@ -443,7 +496,7 @@ vocalize local install --stt
|
|
|
443
496
|
A separate opt-in from Kokoro's `vocalize local install` — nothing here is
|
|
444
497
|
downloaded or built until you run this. It:
|
|
445
498
|
|
|
446
|
-
1. Downloads one whisper.cpp model (`
|
|
499
|
+
1. Downloads one whisper.cpp model (`large-v3-turbo-q5_0` by default, ~547 MB) from a
|
|
447
500
|
pinned Hugging Face revision, verified against a pinned sha256 before
|
|
448
501
|
it's kept.
|
|
449
502
|
2. Compiles and ad-hoc signs a small Swift recorder bundle, **Vocalize
|
|
@@ -460,13 +513,24 @@ more accurate) or `--model base.en` (~141 MB, fastest, least accurate).
|
|
|
460
513
|
### The hotkey
|
|
461
514
|
|
|
462
515
|
```bash
|
|
463
|
-
|
|
516
|
+
vocalize app install
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
installs and starts **Vocalize.app**, a menu-bar app that owns the
|
|
520
|
+
dictation hotkey (and speak/stop) system-wide, no Services menu or
|
|
521
|
+
per-app shortcut assignment needed — see [docs/app.md](docs/app.md) for
|
|
522
|
+
install, uninstall, status and restart. `vocalize dictate` is the same
|
|
523
|
+
command from a terminal, if you'd rather trigger it that way.
|
|
524
|
+
|
|
525
|
+
Prefer a Quick Action instead? That still works:
|
|
526
|
+
|
|
527
|
+
```bash
|
|
528
|
+
vocalize integrate claude
|
|
464
529
|
```
|
|
465
530
|
|
|
466
531
|
then assign a shortcut under **System Settings › Keyboard › Keyboard
|
|
467
532
|
Shortcuts › Services › Text › "Dictate with Vocalize"** — ⌃⌥⌘D is free by
|
|
468
|
-
default and a sensible pick.
|
|
469
|
-
terminal, if you'd rather trigger it that way.
|
|
533
|
+
default and a sensible pick.
|
|
470
534
|
|
|
471
535
|
### How a dictation works
|
|
472
536
|
|
|
@@ -517,10 +581,12 @@ overrides `[stt] max_seconds` for one invocation.
|
|
|
517
581
|
|
|
518
582
|
```toml
|
|
519
583
|
[stt]
|
|
520
|
-
model = "
|
|
521
|
-
language = "en" # a whisper.cpp language code
|
|
584
|
+
model = "large-v3-turbo-q5_0" # base.en | small.en | large-v3-turbo-q5_0 | large-v3-turbo-q8_0
|
|
585
|
+
language = "en" # a whisper.cpp language code ("auto" to detect)
|
|
522
586
|
input_device = "" # "" = system default; else an exact name from --list-devices
|
|
523
|
-
cleanup =
|
|
587
|
+
cleanup = "off" # off | local | claude-cli | anthropic — what tidies the transcript (never audio)
|
|
588
|
+
verbatim = false # true keeps every word even when cleanup is on
|
|
589
|
+
beam_size = 5 # 1-8 whisper.cpp beams; 1 is the greedy decoder
|
|
524
590
|
max_seconds = 120 # 1-600; the recorder self-stops here, dictate backstops it
|
|
525
591
|
sounds = true # the Tink/Pop/Glass feedback sounds
|
|
526
592
|
cues = "sounds" # "sounds" | "words" | "both" — speak "Start."/"Stopped."/"Ready." instead
|
|
@@ -528,10 +594,12 @@ cues = "sounds" # "sounds" | "words" | "both" — speak "Start."/"Stopped
|
|
|
528
594
|
|
|
529
595
|
| Key | Allowed values | Default |
|
|
530
596
|
|---|---|---|
|
|
531
|
-
| `model` | `base.en`, `small.en`, `large-v3-turbo-q5_0` | `
|
|
597
|
+
| `model` | `base.en`, `small.en`, `large-v3-turbo-q5_0`, `large-v3-turbo-q8_0` | `large-v3-turbo-q5_0` |
|
|
532
598
|
| `language` | a whisper.cpp language code (`en`, `es`, `fr`, …); an `.en` model must stay `en` | `en` |
|
|
533
599
|
| `input_device` | `""` (system default) or an exact name from `vocalize listen --list-devices`; ≤ 128 characters, printable, can't start with `-` | `""` |
|
|
534
|
-
| `cleanup` | `
|
|
600
|
+
| `cleanup` | `off`, `local` (0.13), `claude-cli`, `anthropic`; an old `true`/`false` reads as `claude-cli`/`off` | `off` |
|
|
601
|
+
| `verbatim` | `true` / `false` — keep every word even when cleanup is on | `false` |
|
|
602
|
+
| `beam_size` | integer, 1–8 | `5` |
|
|
535
603
|
| `paste` | reserved — not implemented in 0.10.0 | `false` |
|
|
536
604
|
| `max_seconds` | integer, 1–600 | `120` |
|
|
537
605
|
| `sounds` | `true` / `false` | `true` |
|
|
@@ -552,6 +620,37 @@ set it:
|
|
|
552
620
|
input_device = "MacBook Pro Microphone"
|
|
553
621
|
```
|
|
554
622
|
|
|
623
|
+
### Configuration: the `[app]` table
|
|
624
|
+
|
|
625
|
+
The chords the menu-bar app owns, system-wide. A change needs
|
|
626
|
+
`vocalize app restart` before the app picks it up.
|
|
627
|
+
|
|
628
|
+
```toml
|
|
629
|
+
[app]
|
|
630
|
+
dictate = "ctrl+alt+cmd+d" # start/stop dictation
|
|
631
|
+
dictate_mode = "toggle" # toggle | hold ("hold" arrives in 0.13.1)
|
|
632
|
+
speak = "ctrl+alt+cmd+s" # speak the selection
|
|
633
|
+
stop = "ctrl+alt+cmd+x" # stop whatever is playing
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
| Key | Allowed values | Default |
|
|
637
|
+
|---|---|---|
|
|
638
|
+
| `dictate` | a chord, or `""` to disable | `ctrl+alt+cmd+d` |
|
|
639
|
+
| `dictate_mode` | `toggle`, `hold` | `toggle` |
|
|
640
|
+
| `speak` | a chord, or `""` to disable | `ctrl+alt+cmd+s` |
|
|
641
|
+
| `stop` | a chord, or `""` to disable | `ctrl+alt+cmd+x` |
|
|
642
|
+
|
|
643
|
+
**Chord grammar:** tokens joined by `+`. Modifiers are `ctrl`, `alt`,
|
|
644
|
+
`cmd`, `shift` (long spellings `control`, `option`, `command` also work);
|
|
645
|
+
the key is one of `a`-`z`, `0`-`9`, `f1`-`f12`. A chord must include
|
|
646
|
+
`ctrl` or `cmd` — macOS refuses to register the rest. The three chords
|
|
647
|
+
must differ from each other, and `""` disables one.
|
|
648
|
+
|
|
649
|
+
A bad chord is a `ConfigError` naming the key, the value and the legal
|
|
650
|
+
keys — and, like any bad config value, it stops the command you ran, so
|
|
651
|
+
fix it before anything else works. `vocalize settings` prints the four
|
|
652
|
+
`app.*` values in their canonical spelling.
|
|
653
|
+
|
|
555
654
|
### `vocalize status`
|
|
556
655
|
|
|
557
656
|
```bash
|
|
@@ -574,6 +673,17 @@ get four permanent red rows for a feature nobody asked for):
|
|
|
574
673
|
providers and dictation both — is `ok`, 1 otherwise, so it composes with
|
|
575
674
|
`&&` in a script.
|
|
576
675
|
|
|
676
|
+
### `vocalize doctor`
|
|
677
|
+
|
|
678
|
+
Everything `status` checks plus the machine itself: the CLI's own path and
|
|
679
|
+
start-up time, `uv`, `swiftc`, `claude`, the console script's interpreter,
|
|
680
|
+
Hammerspoon, the app bundle and the notes folder. Every row regardless of the
|
|
681
|
+
chain, exit 1 when any row fails. `--json` for scripts.
|
|
682
|
+
|
|
683
|
+
```bash
|
|
684
|
+
vocalize doctor
|
|
685
|
+
```
|
|
686
|
+
|
|
577
687
|
### Continuing an interrupted read
|
|
578
688
|
|
|
579
689
|
Starting a dictation stops any read in progress, but doesn't throw the rest
|
|
@@ -647,15 +757,16 @@ Four Services let you use vocalize from any app without a terminal:
|
|
|
647
757
|
Install all four:
|
|
648
758
|
|
|
649
759
|
```bash
|
|
650
|
-
|
|
760
|
+
vocalize integrate claude
|
|
651
761
|
```
|
|
652
762
|
|
|
653
|
-
This
|
|
654
|
-
`~/Library/Services
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
763
|
+
This installs the `/speak` skill plus the four Quick Action bundles into
|
|
764
|
+
`~/Library/Services/`, with this machine's `vocalize`, `claude`, and
|
|
765
|
+
helper paths baked in (the stable symlinks, not their resolved targets —
|
|
766
|
+
survives a `brew upgrade claude-code`), then refreshes the Services
|
|
767
|
+
registry. Run it from a normal terminal — its PATH is what gets captured.
|
|
768
|
+
To trigger the actions from the keyboard, assign shortcuts under System
|
|
769
|
+
Settings → Keyboard → Keyboard Shortcuts → Services (Stop Vocalize is worth a
|
|
659
770
|
shortcut of its own so you can silence a read from anywhere).
|
|
660
771
|
|
|
661
772
|
Some Electron apps (Claude Code desktop among them) don't expose the
|
|
@@ -867,9 +978,10 @@ model.
|
|
|
867
978
|
there. Use `--no-play` and open the saved file with whatever's on hand.
|
|
868
979
|
- **The disk cache under `~/.cache/vocalize` grows unbounded.** It's
|
|
869
980
|
content-addressed (keyed by a hash of text, voice, model, format, and
|
|
870
|
-
speed),
|
|
871
|
-
|
|
872
|
-
|
|
981
|
+
speed), so it's always safe to delete — except `bin/`, which holds
|
|
982
|
+
Vocalize Recorder and is tied to your microphone grant; deleting that
|
|
983
|
+
forces a rebuild and a re-grant. Delete anything else and nothing will
|
|
984
|
+
break, you'll just re-pay for a re-synthesized clip.
|
|
873
985
|
- **`--api-key` on the command line is visible to other local processes**
|
|
874
986
|
(anything that can run `ps`). Prefer `vocalize auth login`, the
|
|
875
987
|
`ELEVENLABS_API_KEY` environment variable, or a `.env` file instead.
|
|
@@ -908,9 +1020,11 @@ model.
|
|
|
908
1020
|
re-approve it in System Settings › Privacy & Security › Microphone. An
|
|
909
1021
|
install that doesn't change the source never re-signs, so this isn't
|
|
910
1022
|
every upgrade — only ones that touch the recorder.
|
|
911
|
-
-
|
|
912
|
-
|
|
913
|
-
|
|
1023
|
+
- **The smaller models mishear jargon.** `large-v3-turbo-q5_0` is the
|
|
1024
|
+
default because it was the first model to keep "the merge" as two words
|
|
1025
|
+
on the owner's own voice; `small.en` (465 MB) is the lighter choice for a
|
|
1026
|
+
slow Mac but can mangle project-specific words (`pyproject`, a function
|
|
1027
|
+
name) — stay on the default for accuracy, or turn on
|
|
914
1028
|
`[stt] cleanup` so Claude fixes obvious transcription noise before it
|
|
915
1029
|
reaches your clipboard (it still can't guess a word it never heard
|
|
916
1030
|
correctly).
|