interview-coach-cli 0.3.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.
- interview_coach_cli-0.3.0/LICENSE +21 -0
- interview_coach_cli-0.3.0/PKG-INFO +479 -0
- interview_coach_cli-0.3.0/README.md +434 -0
- interview_coach_cli-0.3.0/coach_graph.py +328 -0
- interview_coach_cli-0.3.0/config.py +170 -0
- interview_coach_cli-0.3.0/interview_coach_cli.egg-info/PKG-INFO +479 -0
- interview_coach_cli-0.3.0/interview_coach_cli.egg-info/SOURCES.txt +25 -0
- interview_coach_cli-0.3.0/interview_coach_cli.egg-info/dependency_links.txt +1 -0
- interview_coach_cli-0.3.0/interview_coach_cli.egg-info/entry_points.txt +3 -0
- interview_coach_cli-0.3.0/interview_coach_cli.egg-info/requires.txt +20 -0
- interview_coach_cli-0.3.0/interview_coach_cli.egg-info/top_level.txt +16 -0
- interview_coach_cli-0.3.0/main.py +776 -0
- interview_coach_cli-0.3.0/meeting_plans.py +218 -0
- interview_coach_cli-0.3.0/onboarding.py +189 -0
- interview_coach_cli-0.3.0/plan_wizard.py +175 -0
- interview_coach_cli-0.3.0/profile_store.py +118 -0
- interview_coach_cli-0.3.0/providers.py +252 -0
- interview_coach_cli-0.3.0/pyproject.toml +95 -0
- interview_coach_cli-0.3.0/recorder.py +178 -0
- interview_coach_cli-0.3.0/research.py +314 -0
- interview_coach_cli-0.3.0/responder.py +8 -0
- interview_coach_cli-0.3.0/screen_capture.py +129 -0
- interview_coach_cli-0.3.0/sessions.py +116 -0
- interview_coach_cli-0.3.0/setup.cfg +4 -0
- interview_coach_cli-0.3.0/templates.py +276 -0
- interview_coach_cli-0.3.0/transcriber.py +12 -0
- interview_coach_cli-0.3.0/transcribers.py +161 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ewooral
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: interview-coach-cli
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Voice-driven real-time interview coach: records audio, transcribes with Whisper, answers via Claude/GPT/DeepSeek/Gemini with meeting plans, briefing research, and screen capture.
|
|
5
|
+
Author-email: Ewooral <boahen.cos@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://ewooral.com
|
|
8
|
+
Project-URL: Repository, https://github.com/ewooral/interview-coach-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/ewooral/interview-coach-cli/issues
|
|
10
|
+
Keywords: interview,coach,whisper,claude,voice,cli,transcription,langgraph,meeting,briefing,research
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
22
|
+
Classifier: Topic :: Office/Business
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: sounddevice>=0.4.6
|
|
27
|
+
Requires-Dist: openai-whisper>=20231117
|
|
28
|
+
Requires-Dist: numpy>=1.24.0
|
|
29
|
+
Requires-Dist: scipy>=1.11.0
|
|
30
|
+
Requires-Dist: soundfile>=0.12.0
|
|
31
|
+
Requires-Dist: rich>=13.7.0
|
|
32
|
+
Requires-Dist: anthropic>=0.34.0
|
|
33
|
+
Requires-Dist: openai>=1.40.0
|
|
34
|
+
Requires-Dist: requests>=2.31.0
|
|
35
|
+
Requires-Dist: langgraph>=0.4.0
|
|
36
|
+
Requires-Dist: langchain-core>=0.3.0
|
|
37
|
+
Provides-Extra: gemini
|
|
38
|
+
Requires-Dist: google-genai>=0.3.0; extra == "gemini"
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
42
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
43
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# Interview Coach CLI
|
|
47
|
+
|
|
48
|
+
Voice-driven real-time coaching for any high-stakes conversation — interview, sales discovery, academic call, medical consult, whatever. Captures mic or system audio (Zoom / Teams / Meet), transcribes with Whisper (local, Groq, OpenAI, or Deepgram), and answers with your chosen LLM (Claude / GPT / DeepSeek / Gemini) in a structured `SAY THIS / ANALYSIS / WHY IT WORKS` format.
|
|
49
|
+
|
|
50
|
+
Two-way memory. Multi-profile. Per-conversation meeting plans with agenda, prepared answers, and traps to avoid. Live web-research briefings on your counterparty. Screen capture with vision-LLM analysis for coding challenges and diagrams. LangGraph-based routing that picks a cheap or premium model per turn.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Table of contents
|
|
55
|
+
|
|
56
|
+
1. [Quick start](#quick-start)
|
|
57
|
+
2. [Installation](#installation)
|
|
58
|
+
3. [First-run configuration](#first-run-configuration)
|
|
59
|
+
4. [Concepts](#concepts)
|
|
60
|
+
5. [Running a session](#running-a-session)
|
|
61
|
+
6. [Every hotkey, explained](#every-hotkey-explained)
|
|
62
|
+
7. [Command-line flags](#command-line-flags)
|
|
63
|
+
8. [Meeting plans in depth](#meeting-plans-in-depth)
|
|
64
|
+
9. [Research module](#research-module)
|
|
65
|
+
10. [Screen capture](#screen-capture)
|
|
66
|
+
11. [LLM providers](#llm-providers)
|
|
67
|
+
12. [STT (transcription) providers](#stt-providers)
|
|
68
|
+
13. [Data locations](#data-locations)
|
|
69
|
+
14. [Troubleshooting](#troubleshooting)
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Quick start
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# One-time system dependencies (Ubuntu / Debian):
|
|
77
|
+
sudo apt install -y portaudio19-dev pipewire-utils imagemagick
|
|
78
|
+
|
|
79
|
+
# Copy the env template, then paste your API keys into `.env`
|
|
80
|
+
cp .env.example .env
|
|
81
|
+
chmod 600 .env
|
|
82
|
+
$EDITOR .env
|
|
83
|
+
|
|
84
|
+
# OR: interactive wizard fills .env for you
|
|
85
|
+
interview-recorder --setup
|
|
86
|
+
|
|
87
|
+
# Then create your profile
|
|
88
|
+
interview-recorder --onboard
|
|
89
|
+
|
|
90
|
+
# Optional but recommended: build a meeting plan and briefing before the call
|
|
91
|
+
interview-recorder --make-plan
|
|
92
|
+
interview-recorder --research
|
|
93
|
+
|
|
94
|
+
# Then run the session
|
|
95
|
+
interview-recorder
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Which keys do I actually need?** See [`.env.example`](.env.example) — it lists every env var, groups them by feature, shows recommended combos, and links to where to get each key.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Installation
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# 1. Python dependencies (uses the shared venv in this workspace)
|
|
106
|
+
source /home/ewooral/personal/venv-py3.13/bin/activate
|
|
107
|
+
cd /home/ewooral/personal/cli-interview-recorder
|
|
108
|
+
pip install -r requirements.txt
|
|
109
|
+
|
|
110
|
+
# 2. Global launcher (installs once)
|
|
111
|
+
# Already installed at ~/.local/bin/interview-recorder — usable from any directory.
|
|
112
|
+
|
|
113
|
+
# 3. System deps
|
|
114
|
+
sudo apt install -y portaudio19-dev pipewire-utils imagemagick
|
|
115
|
+
# portaudio: mic capture · pipewire: system-audio monitor · imagemagick: screen capture
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## First-run configuration
|
|
121
|
+
|
|
122
|
+
Two setup wizards run separately:
|
|
123
|
+
|
|
124
|
+
### Provider setup
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
interview-recorder --setup
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
- Pick an LLM provider (Anthropic / OpenAI / DeepSeek / Gemini)
|
|
131
|
+
- Pick an STT provider (local Whisper / Groq / OpenAI / Deepgram)
|
|
132
|
+
- Paste API keys — stored in `.env` (chmod 600) inside the repo
|
|
133
|
+
- Optional: paste **Tavily API key** for the research feature (`TAVILY_API_KEY` in the same `.env`)
|
|
134
|
+
|
|
135
|
+
### Profile onboarding
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
interview-recorder --onboard
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Interactive wizard asks for:
|
|
142
|
+
- Name and pronouns
|
|
143
|
+
- Background (one paragraph — what you've done)
|
|
144
|
+
- Target role / opportunity you're preparing for
|
|
145
|
+
- Strengths to lean on (bullet list)
|
|
146
|
+
- Weaknesses to defuse (bullet list)
|
|
147
|
+
- Extra context (any freeform notes)
|
|
148
|
+
|
|
149
|
+
The profile becomes the persistent "who you are" that the coach uses across every session.
|
|
150
|
+
|
|
151
|
+
Check status any time:
|
|
152
|
+
```bash
|
|
153
|
+
interview-recorder --status
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Concepts
|
|
159
|
+
|
|
160
|
+
The app has four persistent objects:
|
|
161
|
+
|
|
162
|
+
| Object | What it is | Lifespan |
|
|
163
|
+
|--------|-----------|----------|
|
|
164
|
+
| **Profile** | You. Name, background, strengths, weaknesses. | Long-lived. Multiple profiles supported; switch with `--onboard`. |
|
|
165
|
+
| **Template** | Style of coaching. `academic-phd` / `tech-interview` / `product-management` / `sales-discovery` / `medical-residency` / `general`. | Choose per session. |
|
|
166
|
+
| **Meeting plan** | Game plan for one specific upcoming conversation: sections, answers to prep, questions to ask, traps to avoid, briefing on counterparty. | Attach to any number of sessions. |
|
|
167
|
+
| **Session** | The actual live conversation — transcripts + coach responses + which plan/template were used. | Autosaved every turn to SQLite. |
|
|
168
|
+
|
|
169
|
+
At session start you pick: profile (defaults to active) → template → plan (optional) → session (new or continue).
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Running a session
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
interview-recorder # standard flow: pick session → interview loop
|
|
177
|
+
interview-recorder --live # start in auto-stop mode (system audio + VAD)
|
|
178
|
+
interview-recorder --new-session # skip session picker, straight into a fresh one
|
|
179
|
+
interview-recorder --no-plan # skip the plan picker this run
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
At each turn you either **record audio** (default), or **type** the transcript (`t`), or **capture a screenshot** (`c`), or advance the plan (`§`), or fetch fresh research (`b`), or inject live context (`x`). All of these produce a structured coach response in the same format.
|
|
183
|
+
|
|
184
|
+
### Structured coach output
|
|
185
|
+
|
|
186
|
+
Every turn produces three colored panels:
|
|
187
|
+
|
|
188
|
+
- 💬 **SAY THIS** (green) — exact words to speak in the next 30-90 seconds
|
|
189
|
+
- 🧠 **ANALYSIS** (blue) — subtext, traps, what the counterparty is really asking
|
|
190
|
+
- ✨ **WHY IT WORKS** (magenta) — one-line justification for the framing
|
|
191
|
+
|
|
192
|
+
If a meeting plan is active, the coach also references the current agenda section, flags when you're about to hit a listed trap, and reminds you of unanswered questions from your plan.
|
|
193
|
+
|
|
194
|
+
Every turn also shows a routing badge:
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
⚙ turn=question · tier=default · fresh — question needs briefing-informed answer
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
This tells you which model tier the LangGraph coach chose (cheap / default / premium), the turn type it detected, and whether a prepared answer was matched.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Every hotkey, explained
|
|
205
|
+
|
|
206
|
+
At the turn prompt:
|
|
207
|
+
|
|
208
|
+
| Key | Action | Notes |
|
|
209
|
+
|-----|--------|-------|
|
|
210
|
+
| **Enter** | Start recording with the current source | Mic if speaker=you, system audio if speaker=interviewer |
|
|
211
|
+
| **y** | Switch to your voice (mic) | Speaker becomes "you" |
|
|
212
|
+
| **i** | Switch to interviewer (system audio) | Speaker becomes "interviewer" |
|
|
213
|
+
| **l** | Live mode — system audio + auto-stop on silence | For hands-free Zoom / Teams |
|
|
214
|
+
| **t** | Type or paste text as a transcript | Use when audio fails or to paste from chat/email. Prompts for speaker after. |
|
|
215
|
+
| **x** | Add extra context to the coach's memory | Appends to the system prompt for the rest of the session. E.g. "she just mentioned Anthropic — adjust framing." |
|
|
216
|
+
| **c** | Screen capture → vision LLM analysis | For coding questions, whiteboard diagrams, forms. Uses your active LLM in vision mode. |
|
|
217
|
+
| **p** | Show the current meeting plan | Full readout: agenda, answers, questions, traps, commitments, briefing. |
|
|
218
|
+
| **§** or **s** | Advance to next agenda section | Only when a plan is active. Section marker is prepended to future turns. |
|
|
219
|
+
| **b** | Fetch fresh research on someone | Prompts for name + affiliation. Attaches briefing to the current plan and re-renders system prompt. |
|
|
220
|
+
| **n** | Start a new session | Same profile / template / plan, fresh history. |
|
|
221
|
+
| **r** | Rename current session | For organization in the sessions picker. |
|
|
222
|
+
| **q** | Quit | Session is already saved. |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Command-line flags
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
interview-recorder [flags]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Setup & configuration
|
|
233
|
+
|
|
234
|
+
| Flag | Purpose |
|
|
235
|
+
|------|---------|
|
|
236
|
+
| `--setup` | Provider + model + API key wizard |
|
|
237
|
+
| `--status` | Show which providers have keys configured |
|
|
238
|
+
| `--onboard` | Profile wizard (create / edit / switch) |
|
|
239
|
+
| `--edit-profile` | Edit the active profile |
|
|
240
|
+
| `--make-plan` | Build a meeting plan interactively |
|
|
241
|
+
| `--research` | Research a counterparty and attach a briefing to a plan |
|
|
242
|
+
|
|
243
|
+
### Session behavior
|
|
244
|
+
|
|
245
|
+
| Flag | Purpose |
|
|
246
|
+
|------|---------|
|
|
247
|
+
| `--new-session` | Skip the session picker |
|
|
248
|
+
| `--no-plan` | Skip the meeting-plan picker this run |
|
|
249
|
+
| `--live` | Start with system-audio + auto-stop on silence |
|
|
250
|
+
| `--source {mic,system}` | Force a specific audio source |
|
|
251
|
+
| `--silence N` | Silence duration in live mode (default 1.5s) |
|
|
252
|
+
| `--speaker {you,interviewer,unknown}` | Default speaker for this session |
|
|
253
|
+
|
|
254
|
+
### Model choices
|
|
255
|
+
|
|
256
|
+
| Flag | Purpose |
|
|
257
|
+
|------|---------|
|
|
258
|
+
| `--provider {anthropic,openai,deepseek,gemini}` | Override the saved LLM provider |
|
|
259
|
+
| `--llm-model MODEL_ID` | Override the saved LLM model |
|
|
260
|
+
| `--stt {local,groq,openai,deepgram}` | Override the saved STT provider |
|
|
261
|
+
| `--stt-model MODEL_ID` | Override the saved STT model |
|
|
262
|
+
| `--model {tiny,base,small,medium}` | Shortcut for local Whisper model size |
|
|
263
|
+
|
|
264
|
+
### Debug / A/B
|
|
265
|
+
|
|
266
|
+
| Flag | Purpose |
|
|
267
|
+
|------|---------|
|
|
268
|
+
| `--no-graph` | Bypass the LangGraph coach and use the direct single-call path |
|
|
269
|
+
| `--template ID` | Skip the template picker |
|
|
270
|
+
| `--mode {interview,meeting,general}` | Coaching mode preset |
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Meeting plans in depth
|
|
275
|
+
|
|
276
|
+
A meeting plan is a game plan for one specific conversation. When active, it steers the coach's every response.
|
|
277
|
+
|
|
278
|
+
### Creating a plan
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
interview-recorder --make-plan
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
The wizard asks for:
|
|
285
|
+
|
|
286
|
+
- **Title** — how it appears in the picker (e.g., "Call with Dr. Watkins — Oxford")
|
|
287
|
+
- **Counterparty** — name and role of who you're talking with
|
|
288
|
+
- **Purpose** — one paragraph on what you want out of this conversation
|
|
289
|
+
- **Duration** — planned minutes
|
|
290
|
+
- **Sections** — ordered agenda blocks. Each has a title, minutes, and goal.
|
|
291
|
+
- **Answers to prepare** — questions you expect to be asked
|
|
292
|
+
- **Questions to ask** — things you want to learn from them
|
|
293
|
+
- **Traps to avoid** — mistakes to preempt
|
|
294
|
+
- **Commitments** — concrete outcomes you want to leave with
|
|
295
|
+
- **Notes** — freeform
|
|
296
|
+
|
|
297
|
+
### How plans influence the coach
|
|
298
|
+
|
|
299
|
+
When you attach a plan to a session, the coach:
|
|
300
|
+
|
|
301
|
+
- Sees the entire plan in its system prompt on every turn
|
|
302
|
+
- References the current section (`[CURRENT SECTION §N: title]` is prefixed to your transcript before it reaches the LLM)
|
|
303
|
+
- Points out when your prepared answer applies to the interviewer's question
|
|
304
|
+
- Flags when you're walking into a listed trap
|
|
305
|
+
- Reminds you of unasked questions from your list
|
|
306
|
+
- Suggests advancing the section when the current one is winding down
|
|
307
|
+
|
|
308
|
+
### Managing plans
|
|
309
|
+
|
|
310
|
+
- **List:** shown in the picker when starting a session (or press `p` mid-session)
|
|
311
|
+
- **Delete:** `d<n>` in the picker
|
|
312
|
+
- **Rename / edit fields:** currently by running `interview-recorder --make-plan` and picking to overwrite, or editing directly in SQLite
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Research module
|
|
317
|
+
|
|
318
|
+
Given a counterparty's name + optional affiliation, the app runs three parallel searches and synthesizes a briefing.
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
interview-recorder --research
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Sources (all optional; each degrades gracefully):
|
|
325
|
+
|
|
326
|
+
| Source | What it provides | Cost |
|
|
327
|
+
|--------|------------------|------|
|
|
328
|
+
| **Tavily API** | Web search results, news, blog posts, talks, LinkedIn public info | ~$1/1000 queries |
|
|
329
|
+
| **Semantic Scholar** | Academic papers (title, abstract, year, authors) | Free (public API) |
|
|
330
|
+
| **GitHub API** | Bio, repos, followers, code presence | Free (60 req/hr without token) |
|
|
331
|
+
|
|
332
|
+
An LLM synthesis pass turns raw results into a structured briefing:
|
|
333
|
+
|
|
334
|
+
- Snapshot (30-second essentials)
|
|
335
|
+
- Recent focus (last 2 years)
|
|
336
|
+
- Signature themes
|
|
337
|
+
- Tone and style
|
|
338
|
+
- Conversation openings (3-5 questions to raise)
|
|
339
|
+
- Watch-outs
|
|
340
|
+
- Sources cited
|
|
341
|
+
|
|
342
|
+
The briefing is attached to the meeting plan and injected into the coach's system prompt. Every turn from that point on has full context on who you're talking to.
|
|
343
|
+
|
|
344
|
+
### Mid-session research (`b`)
|
|
345
|
+
|
|
346
|
+
If someone new joins the call, press `b`, type their name and affiliation, and the coach fetches + synthesizes a briefing in ~15-20 seconds. Immediately available in subsequent turns.
|
|
347
|
+
|
|
348
|
+
### Tavily key
|
|
349
|
+
|
|
350
|
+
Sign up at https://tavily.com — free tier is 1,000 queries/month. Paste into `.env`:
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
echo "TAVILY_API_KEY=tvly-your-key-here" >> .env
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Screen capture
|
|
359
|
+
|
|
360
|
+
For coding questions, whiteboard diagrams, forms, reference documents:
|
|
361
|
+
|
|
362
|
+
Press `c` at the turn prompt → choose:
|
|
363
|
+
- **r** — region select (drag to define an area)
|
|
364
|
+
- **f** — full screen
|
|
365
|
+
- **w** — click a window (captured whole)
|
|
366
|
+
|
|
367
|
+
The screenshot is saved to `~/.local/share/interview-coach/screens/<session_id>/<timestamp>.png` and sent along with your active system prompt to the LLM's vision endpoint (Claude / GPT / Gemini all support it).
|
|
368
|
+
|
|
369
|
+
You'll be prompted to optionally type a specific question; if you leave it blank, the default prompt is: *"Analyse this screenshot. Identify what's on screen. If it's a question or task, give me a clear answer or approach I can say in the next 30-60 seconds."*
|
|
370
|
+
|
|
371
|
+
The result appears in a bright-cyan **📸 SCREEN ANALYSIS** panel and is saved to session history for reference in future turns.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## LLM providers
|
|
376
|
+
|
|
377
|
+
Configure in `--setup`. All models can be overridden per-session with `--llm-model`.
|
|
378
|
+
|
|
379
|
+
| Provider | Env var | Cheap tier | Default tier | Premium tier |
|
|
380
|
+
|----------|---------|------------|--------------|--------------|
|
|
381
|
+
| Anthropic | `ANTHROPIC_API_KEY` | claude-haiku-4-5 | claude-sonnet-4-6 | claude-opus-4-7 |
|
|
382
|
+
| OpenAI | `OPENAI_API_KEY` | gpt-5-mini | gpt-5-mini | gpt-5 |
|
|
383
|
+
| DeepSeek | `DEEPSEEK_API_KEY` | deepseek-chat | deepseek-chat | deepseek-reasoner |
|
|
384
|
+
| Gemini | `GEMINI_API_KEY` | gemini-2.5-flash | gemini-2.5-flash | gemini-2.5-pro |
|
|
385
|
+
|
|
386
|
+
**Cheapest usable choice:** DeepSeek `deepseek-chat` (~20× cheaper than Claude Haiku). Within Anthropic, Haiku 4.5 is the cost-effective sweet spot.
|
|
387
|
+
|
|
388
|
+
The LangGraph coach picks the cheap tier for small talk and matched-prep answers; the default tier for real questions.
|
|
389
|
+
|
|
390
|
+
Cost estimate: ~$0.001-0.02 per turn with default tier on Claude Sonnet.
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## STT providers
|
|
395
|
+
|
|
396
|
+
Configure in `--setup`. All can be overridden with `--stt`.
|
|
397
|
+
|
|
398
|
+
| Provider | Default model | Latency | Cost |
|
|
399
|
+
|----------|---------------|---------|------|
|
|
400
|
+
| **local** | whisper base (or your choice) | 1-5s local CPU | Free |
|
|
401
|
+
| **groq** | whisper-large-v3-turbo | ~0.5s | Free tier 7200s/min; then ~$0.02/hr |
|
|
402
|
+
| **openai** | gpt-4o-mini-transcribe | ~1-2s | ~$0.006/min |
|
|
403
|
+
| **deepgram** | nova-3 | Streaming | ~$0.0043/min |
|
|
404
|
+
|
|
405
|
+
Local Whisper needs a `.bin` model set in Settings. Groq is recommended for cost + speed. Deepgram is the only true streaming backend.
|
|
406
|
+
|
|
407
|
+
Language: pass `--language en` (default). Whisper supports 100+ languages.
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Data locations
|
|
412
|
+
|
|
413
|
+
| Path | Contents | Lifespan |
|
|
414
|
+
|------|----------|----------|
|
|
415
|
+
| `.env` in repo | API keys (chmod 600, gitignored) | Persistent |
|
|
416
|
+
| `~/.config/interview-coach/config.json` | Last-used provider + model | Persistent |
|
|
417
|
+
| `~/.local/share/interview-coach/sessions.db` | Profiles, sessions, messages, plans, briefings | Persistent |
|
|
418
|
+
| `~/.local/share/interview-coach/screens/<session_id>/` | Captured PNG screenshots | Persistent |
|
|
419
|
+
|
|
420
|
+
Back up by copying `sessions.db` + the screens folder + `.env`.
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Troubleshooting
|
|
425
|
+
|
|
426
|
+
**"No audio captured"**
|
|
427
|
+
- Check mic volume: `wpctl status | grep Microphone`. Boost to 100%: `wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 1.0`
|
|
428
|
+
- Speak closer to the mic; internal laptop mics need less than 30cm distance
|
|
429
|
+
- On Linux, ensure PipeWire is running: `pgrep -af pipewire`
|
|
430
|
+
|
|
431
|
+
**System audio capture fails on Bluetooth**
|
|
432
|
+
- The app dynamically resolves the default sink via `wpctl inspect @DEFAULT_AUDIO_SINK@`. If a new Bluetooth device just connected, kill and restart — sometimes PipeWire caches the previous sink.
|
|
433
|
+
|
|
434
|
+
**Whisper hallucinates "Thank you" repeatedly**
|
|
435
|
+
- Audio is too quiet for the model. Switch to a bigger local model (`--model small` or `medium`), or use Groq/OpenAI which handle low-level audio better.
|
|
436
|
+
|
|
437
|
+
**Coach responses are slow**
|
|
438
|
+
- Check `⚙ tier=` on each turn. If everything says `tier=default`, small talk should be `tier=cheap`. Might be worth restarting to reset the LangGraph state.
|
|
439
|
+
- Try `--no-graph` to A/B compare — if faster, the classifier is misfiring.
|
|
440
|
+
|
|
441
|
+
**"Groq selected but no Groq key set"**
|
|
442
|
+
- The key isn't in `.env`. Run `interview-recorder --setup` and paste.
|
|
443
|
+
|
|
444
|
+
**Provider key seemingly saves but nothing changes**
|
|
445
|
+
- On Linux, the `keyring` crate needs a running secret-service daemon. This CLI uses `.env` directly and doesn't have that issue. The Tauri UI version did — irrelevant here.
|
|
446
|
+
|
|
447
|
+
**Screen capture asks for a window forever**
|
|
448
|
+
- ImageMagick's `import` blocks waiting for a click when no region is passed. Click any window (or click-and-drag for a region). Ctrl+C to cancel.
|
|
449
|
+
|
|
450
|
+
**Semantic Scholar 429s during research**
|
|
451
|
+
- Public API is rate-limited. The pipeline still delivers a useful briefing from web + GitHub + LLM synthesis. If you need paper coverage, sign up for a free Semantic Scholar API key and add `SEMANTIC_SCHOLAR_API_KEY` to `.env` (requires a small code tweak).
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
## Where things live in the code
|
|
456
|
+
|
|
457
|
+
| Module | Responsibility |
|
|
458
|
+
|--------|----------------|
|
|
459
|
+
| `main.py` | CLI entry point, argument parsing, turn loop |
|
|
460
|
+
| `recorder.py` | Audio capture (mic + system audio via PipeWire monitor) |
|
|
461
|
+
| `transcribers.py` | Multi-backend STT dispatch |
|
|
462
|
+
| `providers.py` | Multi-provider LLM dispatch + vision endpoints |
|
|
463
|
+
| `coach_graph.py` | LangGraph state machine for turn routing |
|
|
464
|
+
| `responder.py` | Thin wrapper (legacy) |
|
|
465
|
+
| `config.py` | .env loader + settings storage |
|
|
466
|
+
| `sessions.py` | SQLite schema + session persistence |
|
|
467
|
+
| `profile_store.py` | Profile CRUD |
|
|
468
|
+
| `templates.py` | Coaching prompt templates + `render_prompt(template, profile, plan)` |
|
|
469
|
+
| `meeting_plans.py` | MeetingPlan CRUD + `render_plan_for_prompt` |
|
|
470
|
+
| `plan_wizard.py` | Interactive plan creation and picker |
|
|
471
|
+
| `onboarding.py` | Profile wizard |
|
|
472
|
+
| `research.py` | Tavily + Semantic Scholar + GitHub + LLM synthesis |
|
|
473
|
+
| `screen_capture.py` | Multi-backend screenshot |
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## License
|
|
478
|
+
|
|
479
|
+
MIT. See `LICENSE`.
|