The Problem

Teams need a way to capture meeting content without exposing it to cloud services. Existing transcription tools either stream audio to third‑party APIs or require manual note‑taking, which breaks focus and raises privacy concerns.

What This Does

hyprnote is a self‑hosted suite that listens to audio, runs speech‑to‑text locally (via ONNX‑converted models), and stores the transcript in a Tauri‑based desktop UI. The UI lives in apps/desktop/, the transcription engine in apps/ai/ (apps/ai/src/main.rs), and the HTTP API that powers the web front‑end in apps/api/ (apps/api/src/index.ts). Key files:

  • apps/ai/Dockerfile – builds a Rust container with the transcription pipeline.
  • apps/api/package.json + apps/api/tsconfig.json – define the Node/TypeScript API server.
  • apps/desktop/src/store/zustand/tabs/index.ts – the central Zustand store that 34 other modules import (the “hub” module).
  • packages/agent-core/src/index.ts – provides the LangChain‑style agent used for summarisation.

The codebase is a portfolio of eight loosely coupled projects (apps, crates, plugins, packages, etc.), each with its own build artefacts, rather than a monolithic application.

How It Is Wired

Execution starts in the desktop client:

  1. apps/desktop/src/services/apple-calendar/index.ts exports run (line 29). run invokes useTabs, which calls wrapSliceWithLogging six times, then reaches the UI components that render notes.
  2. The transcription service is launched via the Rust binary built from apps/ai/src/main.rs. This binary is packaged in the apps/ai/Dockerfile and invoked by the desktop via an IPC bridge (see packages/tiptap/src/shared/utils.ts for md2json/json2md conversions).
  3. API requests hit apps/api/src/index.ts, which routes through middleware (apps/api/src/middleware/index.ts) and observability (apps/api/src/observability/index.ts). The API’s fetch function (defined in apps/restate/src/index.ts) is called by many UI components (e.g., SearchResultGroup → cn).

The most widely used utility is packages/utils/src/cn.ts (cn), referenced from 38 places, making it a high‑blast‑radius hotspot. The Zustand store in apps/desktop/src/store/zustand/tabs/index.ts is similarly central, with 34 inbound imports.

A circular import chain exists among apps/desktop/src/store/tinybase/store/settings.ts, apps/desktop/src/config/use-config.ts, and apps/desktop/src/contexts/listener.tsx. This cycle inflates build times and complicates refactoring because any change ripples through the three modules.

Only two functions touch external resources: one reads/writes the SQLite database (via the fetch wrapper) and one reads/writes files (e.g., loading the ONNX model in apps/ai/src/main.rs). All other code is pure computation or UI state management.

How To Use It

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

# 2. Build Rust components (AI transcription, Tauri backend)
cargo build --workspace          # uses Cargo.toml at repo root

# 3. Install and build the desktop UI (Node/TypeScript)
pnpm install                     # pnpm_install action is defined in .github/actions
pnpm run build                  # produces the Tauri bundle

# 4. (Optional) Run the API container
docker build -t hyprnote-api -f apps/api/Dockerfile .
docker run -p 3000:3000 hyprnote-api

Environment variables required by the API are defined in apps/api/.env.example (e.g., OPENAI_API_KEY, POSTHOG_API_KEY). The desktop client reads HYPRNOTE_MODEL_PATH to locate the ONNX model; the default path is set in apps/desktop/src/utils/index.ts.

Real‑World Use

A sales team installs the desktop client on each laptop, points HYPRNOTE_MODEL_PATH at a locally‑hosted Ollama model, and enables the Apple Calendar integration. During a client call, the app records audio, transcribes it in‑process, and stores the transcript in the encrypted local database. After the call, the user clicks “Summarise” – the UI calls packages/agent-core/src/index.ts to run a LangChain agent that produces a bullet‑point recap, which can be exported to Notion via the planned integration.

Code Health & Issues

  • High – Pin GitHub Actions: workflows reference actions by mutable tags (e.g., superfly/flyctl-actions/setup-flyctl@master). Replace with SHA‑pinned versions.
  • High – Vulnerable Dependency: tauri@2.9 has CVE‑2026‑42184. Upgrade to the patched release and update lockfiles.
  • Medium – Enable Dependabot: 209 manifest files lack an update bot; add .github/dependabot.yml.
  • Medium – Pin Docker Base Images: apps/ai/Dockerfile uses mutable tags (rust:${RUST_VERSION}-bookworm). Pin by digest.
  • Medium – Add Dependency‑Vulnerability Scan: CI lacks a dependency review step; integrate dependency-review-action or osv-scanner.
  • Medium – Move Large Binaries to LFS: apps/desktop/src-tauri/resources/libonnxruntime.dylib (31.9 MiB) and ONNX models exceed 5 MiB. Track with Git LFS or fetch from object storage in CI.
  • Medium – Checkout without Persisted Credentials: .github/workflows/desktop_cd.yaml keeps the token after checkout; add with: persist-credentials: false.
  • Low – Set Workflow Timeouts: desktop_cd.yaml lacks timeout-minutes; define a reasonable bound.

The Bottom Line

hyprnote delivers a locally‑hosted, end‑to‑end meeting‑note workflow, but the codebase is fragmented and contains several high‑impact hotspots (central utility modules and import cycles) that increase maintenance risk. Security hygiene needs tightening (pinned actions, base images, and large binaries). Teams comfortable managing Rust/Tauri builds and willing to address the identified hotspots can adopt it for privacy‑first transcription; otherwise the onboarding effort may be non‑trivial.