The Problem

Many professionals need to capture meeting audio, obtain accurate transcripts, and generate concise summaries without sending any data to cloud services. Existing SaaS note‑taking tools either rely on third‑party APIs (exposing confidential content) or require heavyweight local installations that are hard to set up.

What This Does

StenoAI delivers a fully offline workflow for macOS meetings. The repository bundles four self‑contained projects:

ProjectCore purposeKey files
app (desktop UI)Electron‑based macOS client that records audio, shows transcripts and summariesapp/main.js, app/index.html, app/package.json
website (marketing & docs)React‑Vite site that advertises the product and hosts the privacy policywebsite/src/App.jsx, website/package.json
src (backend library)Python modules that drive audio capture, Whisper transcription, Ollama summarization and file‑system organizationsrc/audio_recorder.py, src/transcriber.py, src/summarizer.py, src/ollama_manager.py, src/config.py
prompt_tests (prompt validation)Small test harness for LLM prompt sanity checksprompt_tests/test_prompts.py

The desktop client invokes the Python library via a child process (see app/main.js), passing the recorded file path. The library writes transcripts, summaries and folder metadata under user‑controlled locations defined in src/config.py.

How It Is Wired

Execution starts at app/main.js (the Electron entry point). The script:

  1. Sets up the UI (HTML from app/index.html).
  2. When the user clicks “Record”, it calls the simple_recorder module (Python file simple_recorder.py). This file imports six other modules, making it the most outward‑facing hub (Ca 0 Ce 6).
  3. simple_recorder launches the audio capture loop in src/audio_recorder.py, which writes a raw .wav file to the folder chosen in src/config.py.
  4. After recording, src/transcriber.py runs Whisper (whisper.cpp binary) on the file and returns a transcript.
  5. The transcript is handed to src/summarizer.py, which contacts the local Ollama server via src/ollama_manager.py to obtain a summary.
  6. Summaries and transcripts are persisted by src/models.py (data‑model utilities) and organized by src/folders.py.

The import graph shows no cycles; the widest blast radius lies in simple_recorder (six downstream imports) and src/summarizer.py (deep nesting, 8‑level indentation). All filesystem writes are confined to paths resolved in src/config.py; no external network calls occur beyond the local Ollama HTTP endpoint.

The React front‑end (website/src/App.jsx) is independent of the desktop client; it consumes static assets and does not invoke the Python backend.

How To Use It

# Clone the repo
git clone https://github.com/moses-y/stenoai
cd stenoai

# Install Python deps
python -m pip install -r requirements.txt

# Install desktop UI deps
cd app
npm ci            # uses app/package-lock.json
# start the Electron app (script defined in app/package.json)
npm start

# (Optional) Build the marketing site
cd ../website
npm ci
npm run dev       # Vite dev server, defined in website/package.json

Configuration lives in src/config.py; edit the constants there to change the default storage directory or Ollama endpoint. No environment variables are required out of the box.

Real‑World Use

A legal team installs the DMG release on each Mac. During a client call, the user clicks “Record” in the StenoAI window. The app writes meeting_2023‑08‑22.wav to a secure folder, runs Whisper locally, then invokes Ollama’s llama3.2:3b model to produce a 3‑sentence summary that is saved alongside the transcript. The team can later query the notes with the “Ask Steno” UI without any data ever leaving the device.

Code Health & Issues

  • HIGH – GitHub Actions pinned to tags (apple-actions/import-codesign-certs@v2, softprops/action-gh-release@v1). Replace with commit SHA to prevent supply‑chain drift.
  • HIGHeval/exec over runtime value in app/main.js. Replace with safe parsing (json.loads or ast.literal_eval).
  • MEDIUM – No Dependabot or Renovate config; add .github/dependabot.yml for automatic version bumps.
  • MEDIUM – CI lacks a dependency‑vulnerability scan; integrate dependency-review-action or osv-scanner.
  • MEDIUM – Checkout step keeps the token; set persist-credentials: false and supply a token only where needed.
  • LOW – Workflows have no timeout-minutes; add reasonable limits to avoid hung runs.
  • LOW – Repository lacks convention files (.editorconfig, .gitattributes, formatter config); add them to enforce consistent style.

Measured static analysis also reported:

  • Deep nesting (max depth 8) in src/summarizer.py, simple_recorder.py, src/transcriber.py. Refactor with early returns or helper extraction.
  • Duplicated 6‑line blocks between prompt_tests/test_prompts.py and src/summarizer.py. Consolidate into a shared helper.
  • Bare except clauses in several modules; narrow to specific exception types.
  • Oversized files: app/main.js (≈1856 LOC) and simple_recorder.py. Split into logical sub‑modules.
  • File opened without a context manager in src/audio_recorder.py; use with open(...).

The Bottom Line

StenoAI provides a functional, fully offline meeting‑note pipeline with a clear separation between UI (Electron/React) and processing (Python + Whisper + Ollama). The code works but suffers from maintainability concerns—large, deeply nested files and a few security‑related CI practices. It is suitable for teams that can tolerate some refactoring and want strict data privacy, but it is not ready for production‑grade deployment without addressing the highlighted high‑severity issues.