vybespk 0.1.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.
Files changed (56) hide show
  1. vybespk-0.1.0/.gitignore +19 -0
  2. vybespk-0.1.0/LICENSE.md +105 -0
  3. vybespk-0.1.0/PKG-INFO +424 -0
  4. vybespk-0.1.0/README.md +386 -0
  5. vybespk-0.1.0/brand/README.md +43 -0
  6. vybespk-0.1.0/npm/README.md +19 -0
  7. vybespk-0.1.0/pyproject.toml +63 -0
  8. vybespk-0.1.0/relay/README.md +144 -0
  9. vybespk-0.1.0/voice_agent/__init__.py +9 -0
  10. vybespk-0.1.0/voice_agent/_vendor/__init__.py +0 -0
  11. vybespk-0.1.0/voice_agent/_vendor/faster_whisper/LICENSE +21 -0
  12. vybespk-0.1.0/voice_agent/_vendor/faster_whisper/VENDORED.md +7 -0
  13. vybespk-0.1.0/voice_agent/_vendor/faster_whisper/__init__.py +14 -0
  14. vybespk-0.1.0/voice_agent/_vendor/faster_whisper/audio.py +123 -0
  15. vybespk-0.1.0/voice_agent/_vendor/faster_whisper/feature_extractor.py +230 -0
  16. vybespk-0.1.0/voice_agent/_vendor/faster_whisper/tokenizer.py +320 -0
  17. vybespk-0.1.0/voice_agent/_vendor/faster_whisper/transcribe.py +1941 -0
  18. vybespk-0.1.0/voice_agent/_vendor/faster_whisper/utils.py +152 -0
  19. vybespk-0.1.0/voice_agent/_vendor/faster_whisper/vad.py +351 -0
  20. vybespk-0.1.0/voice_agent/_vendor/faster_whisper/version.py +3 -0
  21. vybespk-0.1.0/voice_agent/activity.py +82 -0
  22. vybespk-0.1.0/voice_agent/agents/__init__.py +196 -0
  23. vybespk-0.1.0/voice_agent/agents/claude_code.py +189 -0
  24. vybespk-0.1.0/voice_agent/agents/codex.py +238 -0
  25. vybespk-0.1.0/voice_agent/audio.py +504 -0
  26. vybespk-0.1.0/voice_agent/billing.py +396 -0
  27. vybespk-0.1.0/voice_agent/cli.py +880 -0
  28. vybespk-0.1.0/voice_agent/config.py +177 -0
  29. vybespk-0.1.0/voice_agent/default_config.toml +160 -0
  30. vybespk-0.1.0/voice_agent/drafter.py +178 -0
  31. vybespk-0.1.0/voice_agent/events.py +51 -0
  32. vybespk-0.1.0/voice_agent/hooks/__init__.py +0 -0
  33. vybespk-0.1.0/voice_agent/hooks/on_notification.py +22 -0
  34. vybespk-0.1.0/voice_agent/hooks/on_permission.py +45 -0
  35. vybespk-0.1.0/voice_agent/hooks/on_prompt.py +28 -0
  36. vybespk-0.1.0/voice_agent/hooks/on_stop.py +31 -0
  37. vybespk-0.1.0/voice_agent/hooks/on_tool.py +20 -0
  38. vybespk-0.1.0/voice_agent/jev.py +73 -0
  39. vybespk-0.1.0/voice_agent/keys.py +66 -0
  40. vybespk-0.1.0/voice_agent/listen.py +1755 -0
  41. vybespk-0.1.0/voice_agent/llm/__init__.py +114 -0
  42. vybespk-0.1.0/voice_agent/llm/anthropic_provider.py +113 -0
  43. vybespk-0.1.0/voice_agent/llm/openai_provider.py +147 -0
  44. vybespk-0.1.0/voice_agent/models.py +138 -0
  45. vybespk-0.1.0/voice_agent/openai_decisions.py +87 -0
  46. vybespk-0.1.0/voice_agent/permissions.py +51 -0
  47. vybespk-0.1.0/voice_agent/research.py +300 -0
  48. vybespk-0.1.0/voice_agent/router.py +256 -0
  49. vybespk-0.1.0/voice_agent/session.py +97 -0
  50. vybespk-0.1.0/voice_agent/settings.py +143 -0
  51. vybespk-0.1.0/voice_agent/share.py +231 -0
  52. vybespk-0.1.0/voice_agent/speaker_id.py +216 -0
  53. vybespk-0.1.0/voice_agent/speech.py +97 -0
  54. vybespk-0.1.0/voice_agent/tmux.py +275 -0
  55. vybespk-0.1.0/voice_agent/transcribe.py +85 -0
  56. vybespk-0.1.0/voice_agent/tts.py +126 -0
@@ -0,0 +1,19 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ .voice-state/
5
+ .voice-models/
6
+ relay/.dev.sqlite
7
+ relay/node_modules/
8
+ relay/.wrangler/
9
+ relay/.dev-share/
10
+ dist/
11
+ npm/*.tgz
12
+ relay/.dev.vars
13
+
14
+ # wrangler files
15
+ .wrangler
16
+ .dev.vars*
17
+ !.dev.vars.example
18
+ .env*
19
+ !.env.example
@@ -0,0 +1,105 @@
1
+ # Functional Source License, Version 1.1, ALv2 Future License
2
+
3
+ ## Abbreviation
4
+
5
+ FSL-1.1-ALv2
6
+
7
+ ## Notice
8
+
9
+ Copyright 2026 Michael Hall
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or
34
+ service that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software
39
+ that exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee
52
+ using the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to
59
+ the infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79
+ EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the Apache License, Version 2.0 that is effective on the second anniversary of
91
+ the date we make the Software available. On or after that date, you may use the
92
+ Software under the Apache License, Version 2.0, in which case the following
93
+ will apply:
94
+
95
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96
+ this file except in compliance with the License.
97
+
98
+ You may obtain a copy of the License at
99
+
100
+ http://www.apache.org/licenses/LICENSE-2.0
101
+
102
+ Unless required by applicable law or agreed to in writing, software distributed
103
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
+ specific language governing permissions and limitations under the License.
vybespk-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,424 @@
1
+ Metadata-Version: 2.5
2
+ Name: vybespk
3
+ Version: 0.1.0
4
+ Summary: Talk to Claude Code or Codex hands-free while you do something else: dictate, ask, approve, and hear what it did.
5
+ Project-URL: Homepage, https://github.com/mikbert/voice
6
+ Author: Mike Hall
7
+ License-Expression: FSL-1.1-ALv2
8
+ License-File: LICENSE.md
9
+ License-File: voice_agent/_vendor/faster_whisper/LICENSE
10
+ Keywords: claude code,codex,coding agent,dictation,speech,tmux,voice
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Environment :: MacOS X
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
21
+ Classifier: Topic :: Software Development
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: anthropic>=2.6
24
+ Requires-Dist: av>=13
25
+ Requires-Dist: certifi>=2024.8
26
+ Requires-Dist: ctranslate2>=4.5
27
+ Requires-Dist: huggingface-hub>=0.26
28
+ Requires-Dist: numpy>=2.0
29
+ Requires-Dist: openai>=3.46
30
+ Requires-Dist: pydantic>=2.10
31
+ Requires-Dist: sherpa-onnx==1.13.8
32
+ Requires-Dist: silero-vad-lite>=0.4
33
+ Requires-Dist: sounddevice>=0.5
34
+ Requires-Dist: soundfile>=0.13
35
+ Requires-Dist: tokenizers>=0.20
36
+ Requires-Dist: tqdm>=4.66
37
+ Description-Content-Type: text/markdown
38
+
39
+ # Vybespk
40
+
41
+ Talk to Claude Code or Codex hands-free while you do something else: washing dishes,
42
+ driving, tidying up. Dictate a prompt in your own words, with pauses as long as you need,
43
+ ask side questions and get spoken answers, approve permission prompts by voice, and hear
44
+ a short summary when the agent finishes. Nothing is sent until you say so.
45
+
46
+ **macOS only for now, with earbuds or a headset with a microphone (AirPods work).** Through the laptop's own speakers it hears itself,
47
+ so earbuds are needed for now. Speech recognition, the voice, and speaker recognition run on your
48
+ Mac. Drafting, summaries, and research use Claude through Vybespk, so no API keys are
49
+ needed: new accounts get $2 of credits to try it (about 5 hours), then Pro or a credit pack.
50
+ Prefer your own Anthropic or OpenAI keys? That's the Own Keys plan.
51
+
52
+ ## Install
53
+
54
+ ```sh
55
+ npx vybespk setup # or: uv tool install vybespk / pipx install vybespk
56
+ ```
57
+
58
+ The coding agent runs inside tmux; if it isn't installed, setup offers to install it with
59
+ Homebrew (`brew install tmux`).
60
+
61
+ `setup` signs you in with a code sent to your email (new accounts get $2 of credits), asks
62
+ how to pay for the AI calls (keep using your credits, Pro, a credit pack, or Own Keys; a
63
+ purchase opens Stripe's checkout and this Mac picks it up when you've paid), and which coding
64
+ agent to drive (Claude Code or Codex). With Own Keys it also asks which LLM (Anthropic or
65
+ OpenAI) and decision model to use and saves your API keys (readable only by you). It
66
+ downloads the local models (about 700 MB, once) and checks everything works. Then, in any
67
+ project folder:
68
+
69
+ ```sh
70
+ vybespk # start the agent here and start listening
71
+ ```
72
+
73
+ You need Claude Code (`npm i -g @anthropic-ai/claude-code`) or Codex
74
+ (`npm i -g @openai/codex`) installed. See `vybespk --help` for every command.
75
+
76
+ ## Development
77
+
78
+ Run from a checkout with `./voicectl` (the same commands as `vybespk`):
79
+
80
+ ```bash
81
+ brew install tmux
82
+ python3 -m venv .venv
83
+ .venv/bin/pip install -e . # vybespk and its dependencies
84
+ export ANTHROPIC_API_KEY=... # drafting, summaries, research
85
+ export JEV_API_KEY=... # routing each utterance (Typesafe JEV)
86
+ ```
87
+
88
+ Settings live in `~/.config/vybespk/config.toml` (only what you change) on top of
89
+ `voice_agent/default_config.toml`; state and models in `~/Library/Application Support/Vybespk`.
90
+ Releasing: see `RELEASE.md`. Below, "`config.toml`" means your settings file; `vybespk
91
+ config` prints every setting with its explanation.
92
+
93
+ ### Use
94
+
95
+ ```bash
96
+ vybespk start ~/path/to/project # Claude Code in tmux, with voice hooks attached
97
+ vybespk send "add a config loader" # type a prompt and press Enter
98
+ vybespk answer yes # answer an open permission dialog
99
+ vybespk interrupt # interrupt the current turn
100
+ vybespk resume [id | "name" | --list] # go back to a Claude Code conversation, by ID or /rename name
101
+ vybespk stop # end the Claude Code session (resume later with claude --resume)
102
+ vybespk restart ~/path/to/other # switch Claude Code to another folder
103
+ vybespk state # ready, busy, dialog, trust, or starting
104
+ vybespk attach # watch or type in the session yourself
105
+ ```
106
+
107
+ Extra Claude Code flags go after `--`, for example
108
+ `vybespk start . -- --permission-mode default`.
109
+
110
+ Hooks are attached only to sessions started by `vybespk`, through `claude --settings`.
111
+ Your normal Claude Code sessions are unaffected.
112
+
113
+ ### One command
114
+
115
+ ```bash
116
+ ./voicectl link # once: installs a `voice` command
117
+ cd ~/Documents/repo/writer
118
+ voice # starts Claude Code in this folder (Opus 5.5, accept-edits mode) and listens
119
+ ```
120
+
121
+ `voice` always uses the folder you run it in. If Claude Code is already running there, it
122
+ reuses it; if it's idle in another folder, it moves it here (the old conversation stays
123
+ resumable). It won't move a Claude Code that is busy or waiting on a permission.
124
+
125
+ ### Talking to it
126
+
127
+ Use headphones or earbuds. Through laptop speakers the microphone hears the assistant's
128
+ own voice, interrupts it, and transcribes it as your speech.
129
+
130
+ ```bash
131
+ vybespk start ~/Documents/repo/myproject -- --permission-mode manual # terminal 1
132
+ vybespk listen # terminal 2
133
+ ```
134
+
135
+ Then just talk, or type in the box at the bottom of the window and press Enter: typed text
136
+ goes the same way as speech, so dictation, questions, "command, ..." and "send it" all work.
137
+ The window shows the draft, anything held, what Claude Code is doing right now (working or
138
+ waiting, for how long, its current step, and its last result), and the last few things the
139
+ assistant said. `vybespk watch` shows Claude Code's own screen, read-only, in another terminal.
140
+
141
+ | Say | What happens |
142
+ |---|---|
143
+ | Describe the work | Builds the draft. A soft pop means the draft changed. |
144
+ | "Actually, make it X" | Rewrites that part of the draft. |
145
+ | Talk to someone else | Dropped, with a bottle sound. Kept until you submit, in case it was for the assistant. |
146
+ | Something ambiguous | Held, with a tink, and asked about when you get back on topic, but only if it's worth asking: the better speech model (small.en) must be confident in it, it must be at least four words, and JEV must judge it related to the current topic. Garbled or unrelated scraps are dropped instead, and "that was me" can still recover them. |
147
+ | Ask it something: "what's the best way to...?" | Answered out loud, with detail on screen. Never added to the draft. |
148
+ | A follow-up: "isn't that heavy?" | Continues the same side discussion. |
149
+ | "Use that" / "add that to the prompt" | Merges the latest answer into the draft. |
150
+ | "Can you hear me?" / "What directory are we in?" | Answers right away from session facts: folder, branch, Claude Code state. |
151
+ | "That was a question for you" | Takes it back out of the draft, held items, or dropped speech, and answers it. |
152
+ | "No, that was for the prompt" / "I was talking to my son" | Moves the earlier utterance where you meant it to go. |
153
+ | "Send it" | Spoken summary of the important parts, then "Shall I send it?" Saying what to send in the same breath ("just put continue in and send that") fills the draft first. |
154
+ | "Yes" | Typed into Claude Code. A glass sound confirms. "Yes?", "yeah", "go ahead" all count; "no" or "not yet" cancels. |
155
+ | "Read it back to me" | The exact prompt text. |
156
+ | "Where were we?" | Topic, draft, held items, last result. |
157
+ | "New topic" / "Start over" / "Scratch that" | As they say. |
158
+ | "Stop" | Interrupts Claude Code's current turn. |
159
+ | A long pause mid-sentence | A sentence that plainly stopped partway ("I'd like you to correct the...") waits up to 2 minutes for the rest, shown on screen as WAITING FOR THE REST. When you speak again, JEV decides whether you're finishing it or starting something new; a command or a new topic leaves it standing alone. |
160
+ | A pause mid-sentence | Anything longer than a command waits 1.5 seconds in case you continue. If you do, the pieces' audio is joined and transcribed once, so Whisper hears the whole sentence. Commands and answers like "send it" or "yes" act at once. |
161
+ | Long speech vs. commands | Two speech models: `base.en` for every utterance and for commands (about 1 s), `small.en` for dictation and longer questions once the sentence is complete (about 3 s on a 2014 Intel Mac, much less on Apple Silicon). Far-away speech: 12% of words wrong with base.en alone, 5% with both. Set `model` and `accurate_model` under `[stt]`. |
162
+ | "Yes" / "No" to a permission | Answers the dialog, with "Allowed." or "Denied." Destructive actions (deleting, pushing, installing, writing outside the project, sending data out) need "yes, I'm sure". A "yes" said to someone else approves nothing. |
163
+ | Answering a question it asked | It confirms with "Got it." |
164
+
165
+ Talking over the assistant cuts it off. What happens next depends on why you cut in:
166
+
167
+ | Interruption | Result |
168
+ |---|---|
169
+ | Noise, or a sound with no words | It resumes on its own once the room is quiet. |
170
+ | Talking to someone else, or "hang on" | It resumes after you go quiet, starting with "As I was saying". |
171
+ | "Go on" / "what were you saying?" | It resumes right away. |
172
+ | Anything else: a question, dictation, a correction | You moved on, so the interrupted reply is dropped. |
173
+
174
+ It replays from the start of the sentence you cut off. Set `resume_after_interrupt` to
175
+ `always` or `never` in `config.toml` to change this. `vybespk barge-ins` shows recent
176
+ interruptions and how each was handled. `vybespk noise-test 30` listens to the room for
177
+ 30 seconds and counts how often noise, such as a dishwasher, running water, or the TV, would
178
+ have cut the assistant off. The session is saved to `session.json` in the state folder
179
+ and survives a restart. `vybespk reset` clears it.
180
+
181
+ ### Testing the router
182
+
183
+ ```bash
184
+ .venv/bin/python -m evals.run_routing # routing and correction cases
185
+ .venv/bin/python -m evals.noise_bargein # synthetic household noise against barge-in
186
+ .venv/bin/python -m evals.interrupt_replay # interruptions: resume, hold, drop, races
187
+ .venv/bin/python -m evals.command_replay # the command keyword and spoken settings
188
+ .venv/bin/python -m evals.fragment_eval # far-away speech in pieces: joined as audio vs not, live JEV calls, under a cent
189
+ ```
190
+
191
+ ### Commands
192
+
193
+ Say **"command"** and then a short phrase, and it's treated as a command, never as
194
+ dictation. Say "command" alone, or ask "what commands are available?" or "which menu options
195
+ do I have?", and it lists them. If you pause after "command", it waits a moment for the
196
+ rest.
197
+
198
+ | Command | What it does |
199
+ |---|---|
200
+ | "command, calibrate my voice" | Learns your voice on the current microphone. It reads each sentence aloud and you repeat it; "skip" skips one, "stop" cancels. |
201
+ | "command, learn my wife's voice" | The same for someone else, so the filter can tell you apart. |
202
+ | "command, pause settings" | Reads the current pauses. |
203
+ | "command, answer wait two seconds" | Changes a pause. Any pause works: end of speech, continuation, answer wait, breath gap, resume wait, barge in, progress, permission reminder. Say a number of seconds, or "longer" or "shorter". |
204
+ | "command, status updates off" / "on" / "every 30 seconds" | Turns the spoken status updates off or on, or changes how often they come. Setting an interval turns them on. Permission reminders play either way. |
205
+ | "command, say one sec after one second" | How long it waits before saying "one sec" while an answer is coming. |
206
+ | "command, which microphone" | Says which microphone it's listening through and why, and whether your earbuds are in music or headset mode. |
207
+ | "command, use the laptop microphone" / "use the earbuds microphone" / "choose the microphone automatically" | Switches microphones for this session. Choosing the Sony earbuds' mic warns that it puts them in headset mode. |
208
+ | "command, permission mode" | Says the current mode, lists the six modes, and asks which you want. "Command, permission mode auto" switches directly. Manual, accept edits, plan, and auto switch in place; don't ask and bypass restart the same conversation. Bypass needs "I'm sure". Your choice becomes the default. Same as `voice mode auto`. |
209
+ | "mute" / "unmute" | Said on its own (or after "command"). While muted, Vybespk acts on nothing it hears or is typed until you say "unmute", and only your voice unmutes it. Handy for a phone call. "The mute button should be red" is still dictation. |
210
+ | "command, resume the last session" | Restarts Claude Code on the conversation before the current one, in that conversation's folder. Refused while Claude Code is busy. Same as `vybespk resume`; `vybespk resume --list` shows recent and named ones. |
211
+ | "command, resume the voice agent session" | The same, by the name you gave a session with `/rename`. Same as `vybespk resume "voice agent"`. |
212
+ | "command, send it", "read it back", "where were we", "scratch that", "start over", "new topic", "stop" | The usual controls, without any chance of being taken as dictation. |
213
+
214
+ The same requests also work without the keyword, such as "wait two seconds before you
215
+ answer", when they're clear. Changes are saved to your settings file (`~/.config/vybespk/config.toml`).
216
+
217
+ ### Recognizing your voice
218
+
219
+ Once you enroll, only your voice reaches the prompt, and only your voice can interrupt the
220
+ assistant. Your wife, your son, and the TV are dropped, and that speech is still logged, so
221
+ "that was me" brings it back.
222
+
223
+ ```bash
224
+ vybespk enroll # read ten sentences, about a minute; do it once per microphone
225
+ # (or, while listening, say "command, calibrate my voice")
226
+ vybespk enroll wife # optional, a few sentences each; makes the filter much sharper
227
+ vybespk enroll son
228
+ vybespk whois 30 # talk, have others talk, and see what it decides
229
+ vybespk enroll --list # profiles, pitch, and your threshold
230
+ ```
231
+
232
+ It uses a WeSpeaker voice model through sherpa-onnx (about 75 ms per utterance) plus pitch:
233
+ a voice much higher than yours counts as someone else. Each utterance is judged "me",
234
+ "other", or "unsure"; unsure speech goes through as before. A barge-in is checked after 0.6 s
235
+ of speech, and again at 1.2 s if unsure; doubtful cases lean toward letting you in. Tune
236
+ `[speaker_id]` in `config.toml` if needed.
237
+
238
+ ### Voice
239
+
240
+ Speech uses a local Piper neural voice through sherpa-onnx, with macOS `say` as the
241
+ fallback. Nothing leaves the Mac.
242
+
243
+ ```bash
244
+ .venv/bin/pip install --only-binary=:all: "sherpa-onnx==1.13.8" # 2.x drops Piper's pronouncer
245
+ vybespk voices # list voices, * marks the current one
246
+ vybespk voice-test en_US-lessac-high # hear one (downloads it if needed)
247
+ vybespk voice en_US-lessac-high # switch, then restart listen
248
+ ```
249
+
250
+ Voices live in the models folder (`~/Library/Application Support/Vybespk/models`). Measured on a 2014 Intel MacBook Pro,
251
+ "medium" voices generate about 17 times faster than real time and "high" voices about 3
252
+ times, so "high" voices start each reply roughly a second later. While AirPods or other
253
+ Bluetooth earbuds have their microphone in use, playback drops to phone-call quality
254
+ whichever voice you pick; a separate microphone keeps it at full quality.
255
+
256
+ Some earbuds sound distorted in that headset mode. On this Mac the Sony WF-1000XM5 are clear
257
+ in music mode and garbled in headset mode, so they're listed in `output_only_devices` in
258
+ `config.toml`: while they're the output, the listener hears through the laptop microphone
259
+ and they stay in music mode. AirPods use their own microphone as usual. Voice recognition
260
+ is per microphone, so calibrate once on the laptop mic too ("command, calibrate my voice").
261
+
262
+ ### Models
263
+
264
+ | Work | Model |
265
+ |---|---|
266
+ | Routing every utterance | JEV (`jev-1.14.0`) |
267
+ | Drafting, quick replies, spoken summaries | Claude Haiku 5.5 |
268
+ | Side questions: searches, quick lookups, basic coding questions | Claude Sonnet 5.5 (low effort for simple lookups) |
269
+ | Complex questions: code analysis, debugging, design, "dig into this" | Claude Opus 5.5 |
270
+ | Claude Code, for every prompt you submit | Claude Opus 5.5 or stronger |
271
+
272
+ `vybespk start` always launches Claude Code with `--model claude-opus-5-5` (set in
273
+ `[claude_code]` in `config.toml`; Fable 5.1 and Mythos 5.1 are also allowed). Before each
274
+ voice prompt is submitted, the bridge checks the model on screen. If it's weaker, it
275
+ restarts Claude Code on Opus 5.5 with `--resume`, keeping the conversation, and then sends.
276
+ It never uses `/model`, because that also changes your default for every new session.
277
+
278
+ Questions never stop Claude Code. Only an explicit "stop", "cancel", or "abort" does.
279
+
280
+ Claude Code starts in `acceptEdits` mode by default (`permission_mode` in `config.toml`), so
281
+ file reads and edits in the project don't ask; other shell commands still do. A permission
282
+ prompt is never dropped: if it's cut off or goes unanswered, it's asked again when you're
283
+ quiet, and every 30 seconds it reminds you that Claude Code is waiting.
284
+
285
+ ### Setup: coding agent, LLM, and decision model
286
+
287
+ Three settings, each its own choice in `config.toml`:
288
+
289
+ | Setting | Options | What it is |
290
+ |---|---|---|
291
+ | `[agent] name` | `claude_code`, `codex` | The coding agent the voice agent drives in tmux |
292
+ | `[llm] provider` | `anthropic`, `openai` | The LLM behind drafting, summaries, quick replies, research |
293
+ | `[llm] decisions` | `jev`, `openai` | The decision model that routes every utterance |
294
+
295
+ ```sh
296
+ vybespk setup # ask each question, save the keys each choice needs, test them
297
+ vybespk setup openai # everything on OpenAI: Codex + GPT models + Decisions API
298
+ vybespk setup anthropic # Claude Code + Claude models + JEV
299
+ vybespk setup show # what's chosen, and where each key comes from
300
+ ```
301
+
302
+ Model tiers are per provider (`[llm.anthropic]`, `[llm.openai]`): `fast` for drafting and
303
+ summaries (Haiku 5.5 / GPT-6 Luna), `research` (Sonnet 5.5 / GPT-6.1 Sol), and `deep`
304
+ (Opus 5.5 / GPT-6 Astra). Codex runs on `gpt-6.1-sol` or stronger (`[codex]`), as Claude
305
+ Code runs on Opus 5.5 or stronger. Adding a provider or agent is one module:
306
+ `voice_agent/llm/<name>_provider.py` or `voice_agent/agents/<name>.py`.
307
+
308
+ Codex permission modes, by voice ("command, permission mode") or `vybespk mode`:
309
+ read only, workspace (the default: edits and runs commands in the project, asks about
310
+ anything outside it), auto review, full access, and no approvals (needs "I'm sure"). Every
311
+ switch restarts the same conversation. The first time Codex starts with the voice hooks it
312
+ asks you to trust them; choose "Review hooks" if you have other hooks of your own, or
313
+ "Trust all and continue". It asks again only if the hooks change.
314
+
315
+ Keys are saved in `~/.config/voice/keys.json`, readable only by you; a key set in your
316
+ shell takes precedence. These choices apply with Own Keys; otherwise the AI calls go through
317
+ Vybespk with Claude and JEV and no keys are needed.
318
+
319
+ ### Plans and usage
320
+
321
+ Everyone signs in (`vybespk login`): a 6-digit code is emailed, and the same address signs
322
+ you in on up to 3 Macs.
323
+
324
+ | Plan | How it's paid |
325
+ |---|---|
326
+ | Trial | $2 of credits when you sign up, about 5 hours of use. No API keys needed. |
327
+ | Credits | Prepaid packs ($10, $20). Each call comes off your balance at twice its API cost. |
328
+ | Pro, $12/month | Everything included except research, which gets 60 questions a month; past that, research uses credits. Includes Own Keys. |
329
+ | Own Keys, $5/month | Your own Anthropic or OpenAI (and JEV) keys pay for the AI calls, which go straight to the provider. |
330
+
331
+ ```sh
332
+ vybespk usage [days] # every model call on this machine and what it cost, on any plan
333
+ vybespk buy # pick a plan; checkout opens in your browser, this Mac activates when paid
334
+ vybespk plan # your plan, credits left, research questions used
335
+ vybespk billing # cancel Pro, change your card, see receipts and invoices
336
+ vybespk login # sign in on this Mac (or another one) with a code by email
337
+ vybespk logout # sign this Mac out; frees its slot
338
+ ```
339
+
340
+ ```sh
341
+ vybespk share on # opt in to sharing your data; earns $2 of credits a month
342
+ vybespk share status # what's waiting to upload, progress toward this month's reward
343
+ vybespk share off # stop, and delete anything not yet uploaded
344
+ ```
345
+
346
+ Sharing collects each utterance's audio and transcripts, how it was handled, the prompts
347
+ you send, and research answers. It never includes speech the voice filter says is someone
348
+ else's, or anything that looks like a password or key. The reward is $2 of credits for a
349
+ month with at least 200 utterances on 3 or more days. A license works on up to 3 machines;
350
+ `vybespk deactivate` frees one.
351
+
352
+ On a plan, the voice agent's own models are Claude and JEV through our relay at
353
+ `api.vybespk.com`, whatever LLM setting you chose. The coding agent still runs on your own
354
+ account: Codex on your OpenAI or ChatGPT sign-in, Claude Code on your Claude one.
355
+
356
+ Payments go through Stripe, which is the seller of record: it handles sales tax and VAT and
357
+ sends receipts. Paid plans go through the relay in `relay/` (see `relay/README.md` to deploy it). When a
358
+ paid plan runs out, the assistant says so ("You're out of research questions this month")
359
+ and keeps doing whatever's still covered.
360
+
361
+ ### Progress while you wait
362
+
363
+ Status updates yield to you: the moment you start talking, an update stops mid-sentence
364
+ (no voice check, since it's low-stakes), and once you've been quiet for a few seconds a fresh
365
+ one plays with the current status. "Command, update quiet two seconds" changes how long it
366
+ waits.
367
+
368
+ When a question is accepted you hear a soft tone. If the answer takes more than 5 seconds
369
+ it says "One sec." During long research or a long Claude Code task, it says a few words
370
+ about what's happening about every 12 seconds, such as "Claude Code is running the unit
371
+ tests" or "Checking how the speaker picks the next item." Updates never play while you're
372
+ talking. Claude Code updates come from hooks, so restart a session started before this
373
+ change to get them.
374
+
375
+ ### What the assistant can and can't do itself
376
+
377
+ It reads: project files, read-only git (status, log, diff, show, branch, blame), and
378
+ listing commands (ls, find, du) in your home folder. Anything that changes something,
379
+ such as edits, tests, builds, commits, or installs, goes to Claude Code through the draft,
380
+ after you confirm.
381
+
382
+ ### What the hooks do
383
+
384
+ | Hook | Behavior |
385
+ |---|---|
386
+ | Stop | Summarizes Claude Code's final response with Claude Haiku 5.5 and speaks it. Short plain replies are spoken as they are. |
387
+ | PermissionRequest | Speaks what Claude Code wants to do, such as "Claude wants to write todo.txt. Allow it?" |
388
+ | Notification | Speaks elicitation and needs-input notifications. |
389
+
390
+ All hooks run async, so they never block Claude Code. Spoken text is logged to
391
+ `spoken.log` in the state folder.
392
+
393
+ ## Spike findings
394
+
395
+ - Bracketed paste through `tmux paste-buffer -p` delivers multi-line prompts as one
396
+ message. Embedded newlines do not submit early.
397
+ - Keys sent while Claude Code is starting are silently dropped. The bridge now waits for
398
+ the input box before typing.
399
+ - The folder trust dialog defaults to "No, exit". The bridge reports it rather than
400
+ accepting it, so trusting a folder stays a human decision.
401
+ - The Stop hook receives the final response text directly. Summary latency is about 0.7
402
+ to 1 second on Claude Haiku 5.5. Most of the wait you hear is speech playback.
403
+ - The summary is much better when it knows what was asked. The bridge records each prompt
404
+ it sends and passes it to the summarizer.
405
+ - Not every tool call raises a permission dialog. Answer keys are sent only when a
406
+ dialog is actually on screen, otherwise they would land in the prompt box as text.
407
+ - Escape interrupts a running turn. The Stop hook does not fire on interrupt.
408
+ - Your default permission mode is auto, which approves most actions without a dialog.
409
+ Use `--permission-mode default` to hear permission prompts.
410
+
411
+ ## Known gaps for later phases
412
+
413
+ - Pane state is detected by matching on-screen text, which can break when Claude Code's
414
+ TUI changes. A hook-driven state file would be sturdier.
415
+ - No destructive-action phrase check yet. "Yes" approves any dialog.
416
+ - Prompts typed by hand in the session are not recorded, so their summaries lack the
417
+ request context. The transcript path in the hook input can fix this.
418
+ - Background task completions produce extra spoken summaries.
419
+
420
+ ## License
421
+
422
+ [Functional Source License 1.1, Apache 2.0 future license](LICENSE.md) (FSL-1.1-ALv2): use, change
423
+ and share it for anything except a competing product; each version becomes Apache 2.0 two
424
+ years after release. faster-whisper, vendored in `voice_agent/_vendor/`, is MIT.