Repository: https://github.com/priankr/lognotes
Local speech-to-text dictation app. Push-to-talk hotkey → Whisper transcribes → paste at cursor. Settings / Activity / Logs tabs and a draggable recording overlay.
LogNotes is a hybrid app: an Electron front end (UI) over a Python back end (the "sidecar") that runs the ML pipeline and OS integration. They are separate processes talking over a loopback WebSocket. The ML stack stays in Python because there is no production-quality JS equivalent.
See ARCHITECTURE.md for the full architecture (pipeline, IPC protocol, module layout, packaging, security).
- App (Electron):
cd electron && npm start— spawns the Python back end (sidecar.py) and connects over a loopback WebSocket. - Back end alone (headless):
python sidecar.py. - Packaged:
build\build-electron.ps1→dist-electron\LogNotes Setup *.exe(bundles the back end asdist\LogNotes\LogNotes.exe).
- src/controller.py —
LogNotesController, the front-end-agnostic orchestrator (recorder → Whisper → paste). Talks to the UI only via an injectedUIBridge/ConfigStore/ActivityStore. - sidecar.py —
SidecarServer: WebSocket + RPC server wrapping the controller;HeadlessBridgeforwards UI calls as events. - src/ui_bridge.py —
UIBridgeprotocol the controller talks through. - src/config.py — schema, whitelist validation,
0o600save,ConfigStore. - src/activity.py — in-memory
ActivityStore(session-scoped, audio in RAM only). - src/transcription/ — faster-whisper, model registry, CUDA detection.
- src/audio/ —
AudioRecorder(sounddevice). - src/input/ —
HotkeyListener(pynput),paste_text/copy_to_clipboard. - src/paths.py — dev-vs-frozen asset resolution + user data/cache dirs.
- electron/ —
main.js(process spawn, tray, lifecycle),preload.js(bridge),renderer/(tabs + overlay). - build/ — PyInstaller specs +
build-electron.ps1(Electron build).
A legacy Tkinter UI (src/ui/, entry main.py) is kept for reference and shares
LogNotesController. The Electron app is canonical.
- Checkpoint pasting — segments are pasted as sentence-boundary chunks so partial output is preserved if processing fails mid-stream.
- Activity tab — every session transcription retained in RAM (audio + text), retryable with a different Whisper model. Nothing persisted to disk; cleared on app close. Audio is never serialized over IPC — only metadata + text.
- Config lives at
%APPDATA%\LogNotes\config.json(shared between dev and packaged runs). All values are whitelist-validated on load;setConfigover IPC re-validates per key. - Model caches at
%LOCALAPPDATA%\LogNotes\cache\{hf,torch};HF_HOME/TORCH_HOMEset in the entry point (sidecar.py / main.py) before torch imports.
- All markdown section headings use title case (e.g. "Hotkey Not Working", not "Hotkey not working"). This applies to README.md and all files under
documentation/.
sys.stdout/sys.stderrareNoneunder--noconsole; the entry points replace them withio.StringIOsinks so libraries that call.write()(torch.hub) don't crash. The frozen back end usesconsole=Trueso itsPORT <n>handshake reaches a real stdout.- Do not add
testorunittestto PyInstallerexcludes— torch importsunittestat runtime. - Rebuilding fails if a running
LogNotes.exeis still holdingdist-electron\win-unpacked\(locked files). Close the app (and any orphaned back ends) first. - electron-builder can't edit the exe to embed the icon on this setup (winCodeSign symlink failure); the build embeds the icon via
rceditin a three-stage build. See ARCHITECTURE.md packaging notes. build.ps1/build-electron.ps1must stay ASCII-only — Windows PowerShell 5.1 mis-parses UTF-8 without a BOM.
venv\Scripts\python.exe -m unittest discover -s tests — config validation, status revert, and the sidecar protocol smoke test.