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.
@@ -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`.