8000 GitHub - n-pinkerton/echo-draft: Voice-to-text dictation app with local (Nvidia Parakeet/Whisper) and cloud models (BYOK). Privacy-first and available cross-platform. · GitHub
[go: up one dir, main page]

Skip to content

About

Voice-to-text dictation app with local (Nvidia Parakeet/Whisper) and cloud models (BYOK). Privacy-first and available cross-platform.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

 
 

Latest commit

 

History

650 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EchoDraft

Downloads

An open source desktop dictation application that converts speech to text using OpenAI Whisper. Features both local and cloud processing options for maximum flexibility and privacy.

Documentation

For maintainers, contributors, and coding agents:

Star History

Star History Chart

License

This project is licensed under the MIT License - see the LICENSE file for details. This means you can freely use, modify, and distribute this software for personal or commercial purposes.

Features

  • ☁️ EchoDraft Cloud: Sign in and transcribe instantly — no API keys needed, with free and Pro plans
  • 🔐 Account System: Google OAuth and email/password sign-in with email verification
  • 💳 Subscription Management: Free tier (2,000 words/week), Pro tier (unlimited), 7-day free trial
  • 🎤 Global Hotkey: Customizable hotkey to start/stop dictation from anywhere (default: backtick `)
  • 🤖 Multi-Provider AI Cleanup: Choose between OpenAI, Anthropic Claude, Google Gemini, or local models
  • 🛡️ Protected Cleanup Policy: Fixed cleanup-only prompts preserve dictated intent and never execute dictated requests
  • 🧠 Multi-Provider AI:
    • OpenAI cleanup: GPT-5.6 Terra (balanced default), GPT-5.6 Luna (fast), and GPT-5.6 Sol (highest quality)
    • Anthropic: Claude Opus 4.5, Claude Sonnet 4.5
    • Google: Gemini 2.5 Pro/Flash/Flash-Lite
    • Groq: Ultra-fast inference with Llama and Mixtral models
    • Local: Qwen, LLaMA, Mistral models via llama.cpp
  • 🔒 Privacy-First: Local processing keeps your voice data completely private
  • 🎨 Modern UI: Built with React 19, TypeScript, and Tailwind CSS v4
  • 🚀 Fast: Optimized with Vite and modern tooling
  • 📱 Control Panel: Manage settings, view history, and configure API keys
  • 🗄️ Transcription History: SQLite database stores all your transcriptions locally
  • 🔧 Model Management: Download and manage local Whisper models (tiny, base, small, medium, large, turbo)
  • ⚡ NVIDIA Parakeet: Fast local transcription via sherpa-onnx (multilingual, 25 languages)
  • 🧹 Model Cleanup: One-click removal of cached Whisper models with uninstall hooks to keep disks tidy
  • 🌐 Cross-Platform: Works on macOS, Windows, and Linux
  • ⚡ Automatic Pasting: Transcribed text automatically pastes at your cursor location
  • 🧵 Stacked Dictation: Start another recording while earlier audio is processing; jobs are delivered in recording order
  • 🧭 Tray-First Interface: Use the system tray icon for dictation status, last-copy actions, settings, and app access
  • 🔄 OpenAI Responses API: Using the latest Responses API for improved performance
  • 🛡️ Preservation-First Cleanup: Suspicious compression, changed polarity, missing literals, or assistant-style execution triggers a model-guided repair using the rejected draft and safety reasons, then safely falls back to the original text if needed
  • 🌐 Globe Key Toggle (macOS): Optional Fn/Globe key listener for a hardware-level dictation trigger
  • ⌨️ Compound Hotkeys: Support for multi-key combinations like Cmd+Shift+K
  • 🎙️ Push-to-Talk (Windows): Native low-level keyboard hook for true push-to-talk with compound hotkey support
  • 📖 Custom Dictionary: Add words, names, and technical terms to improve transcription accuracy
  • 🐧 GNOME Wayland Support: Native global shortcuts via D-Bus for GNOME Wayland users

Prerequisites

  • Node.js 18+ and npm (Download from nodejs.org)
  • macOS 10.15+, Windows 10+, or Linux
  • On macOS, Globe key support requires the Xcode Command Line Tools (xcode-select --install) so the bundled Swift helper can run

Quick Start

For Personal Use (Recommended)

  1. Clone the repository:

    git clone https://github.com/n-pinkerton/echo-draft.git
    cd echo-draft
  2. Install dependencies:

    npm install
  3. Optional: Set up API keys (only needed for cloud processing):

    Method A - Environment file:

    cp .env.example .env
    # Edit .env and add your API keys:
    # OPENAI_API_KEY=your_openai_key
    # ANTHROPIC_API_KEY=your_anthropic_key
    # GEMINI_API_KEY=your_gemini_key
    # GROQ_API_KEY=your_groq_key
    # MISTRAL_API_KEY=your_mistral_key

    Method B - In-app configuration:

    • Run the app and configure API keys through the Control Panel
    • Keys are automatically saved and persist across app restarts
  4. Build the application:

    npm run build
  5. Run the application:

    npm run dev  # Development mode with hot reload
    # OR
    npm start    # Production mode
  6. Optional: Local Whisper from source (only needed if you want local processing):

    npm run download:whisper-cpp

    This downloads the whisper.cpp binary for your current platform into resources/bin/.

Building for Personal Use (Optional)

If you want to build a standalone app for personal use:

# Build without code signing (no certificates required)
npm run pack

# The unsigned app will be in: dist/mac-arm64/EchoDraft.app (macOS)
# or dist/win-unpacked/EchoDraft.exe (Windows)
# or dist/linux-unpacked/echodraft (Linux)

Note: On macOS, you may see a security warning when first opening the unsigned app. Right-click and select "Open" to bypass this.

Linux (Multiple Package Formats)

EchoDraft now supports multiple Linux package formats for maximum compatibility:

Available Formats:

  • .deb - Debian, Ubuntu, Linux Mint, Pop!_OS
  • .rpm - Fedora, Red Hat, CentOS, openSUSE
  • .tar.gz - Universal archive (works on any distro)
  • .flatpak - Sandboxed cross-distro package
  • AppImage - Portable single-file executable

Building Linux Packages:

# Build default Linux package formats (AppImage, deb, rpm, tar.gz)
npm run build:linux

# Find packages in dist/:
# - EchoDraft-x.x.x-linux-x64.AppImage
# - EchoDraft-x.x.x-linux-x64.deb
# - EchoDraft-x.x.x-linux-x64.rpm
# - EchoDraft-x.x.x-linux-x64.tar.gz

Optional: Building Flatpak (requires additional setup):

# Install Flatpak build tools
sudo apt install flatpak flatpak-builder  # Debian/Ubuntu
# OR
sudo dnf install flatpak flatpak-builder  # Fedora/RHEL

# Add Flathub repository and install runtime
flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install --user -y flathub org.freedesktop.Platform//24.08 org.freedesktop.Sdk//24.08

# Add "flatpak" to linux.target in electron-builder.cjs, then build
npm run build:linux

Installation Examples:

# Debian/Ubuntu
sudo apt install ./dist/EchoDraft-*-linux-x64.deb

# Fedora/RHEL
sudo dnf install ./dist/EchoDraft-*-linux-x64.rpm

# Universal tar.gz (no root required)
tar -xzf dist/EchoDraft-*-linux-x64.tar.gz
cd EchoDraft-*/
./echodraft

# Flatpak
flatpak install --user ./dist/EchoDraft-*-linux-x64.flatpak

# AppImage (existing method)
chmod +x dist/EchoDraft-*.AppImage
./dist/EchoDraft-*.AppImage

Optional Dependencies for Automatic Paste:

The clipboard paste feature requires platform-specific tools:

X11 (Traditional Linux Desktop):

# Debian/Ubuntu
sudo apt install xdotool

# Fedora/RHEL
sudo dnf install xdotool

# Arch
sudo pacman -S xdotool

Wayland (Modern Linux Desktop):

Recommended: Install wl-clipboard for reliable clipboard sharing between Wayland apps:

sudo apt install wl-clipboard    # Debian/Ubuntu
sudo dnf install wl-clipboard    # Fedora/RHEL
sudo pacman -S wl-clipboard      # Arch

Choose one of the following paste tools:

Option 1: wtype (requires virtual keyboard protocol support)

# Debian/Ubuntu
sudo apt install wtype

# Fedora/RHEL
sudo dnf install wtype

# Arch
sudo pacman -S wtype

Option 2: ydotool (works on more compositors, requires daemon)

# Debian/Ubuntu
sudo apt install ydotool
sudo systemctl enable --now ydotoold

# Fedora/RHEL
sudo dnf install ydotool
sudo systemctl enable --now ydotoold

# Arch
sudo pacman -S ydotool
sudo systemctl enable --now ydotoold

Terminal Detection (Optional - for KDE Wayland users):

# On KDE Wayland, kdotool enables automatic terminal detection
# to paste with Ctrl+Shift+V instead of Ctrl+V
sudo apt install kdotool  # Debian/Ubuntu
sudo dnf install kdotool  # Fedora/RHEL
sudo pacman -S kdotool    # Arch

ℹ️ Note: EchoDraft automatically tries paste tools in this order: wtype → ydotool → xdotool (for XWayland apps). If no paste tool is installed, text will still be copied to the clipboard - you'll just need to paste manually with Ctrl+V.

⚠️ ydotool Requirements: The ydotoold daemon must be running for ydotool to work. Start it manually with sudo ydotoold & or enable the systemd service as shown above.

GNOME Wayland Global Hotkeys:

On GNOME Wayland, Electron's standard global shortcuts don't work due to Wayland's security model. EchoDraft automatically uses native GNOME keyboard shortcuts via D-Bus and gsettings:

  • Hotkeys are registered as GNOME custom shortcuts (visible in Settings → Keyboard → Shortcuts)
  • Default hotkey is Alt+R (backtick not supported on GNOME Wayland)
  • Push-to-talk mode is not available on GNOME Wayland (only tap-to-talk)
  • Falls back to X11/XWayland shortcuts if GNOME integration fails
  • No additional dependencies required - uses dbus-next npm package

ℹ️ GNOME Wayland Limitation: GNOME system shortcuts only fire a single toggle event (no key-up detection), so push-to-talk mode cannot work. The app automatically uses tap-to-talk mode on GNOME Wayland.

🔒 Flatpak Security: The Flatpak package includes sandboxing with explicit permissions for microphone, clipboard, and file access. See electron-builder.cjs for the complete permission list.

Building for Distribution

For maintainers who need to distribute signed builds:

# Configured certificates are required for signed distribution artifacts
npm run build:mac    # macOS (requires Apple Developer account)
npm run build:win    # Windows (unsigned unless a code signing cert is configured)
npm run build:linux  # Linux

First Time Setup

  1. Choose Processing Method:

    • EchoDraft Cloud: Sign in for instant cloud transcription with free and Pro plans
    • Bring Your Own Key: Use your own OpenAI/Groq/AssemblyAI API keys
    • Local Processing: Download Whisper or Parakeet models for completely private transcription
  2. Grant Permissions:

    • Microphone Access: Required for voice recording
    • Accessibility Permissions: Required for automatic text pasting (macOS)
  3. Name Your Agent: Give your AI assistant a personal name (e.g., "Assistant", "Jarvis", "Alex")

    • Makes interactions feel more natural and conversational
    • Helps distinguish between giving commands and regular dictation
    • Can be changed anytime in settings
  4. Configure Global Hotkey: Default is backtick (`) but can be customized

Usage

Basic Dictation

  1. Start the app - EchoDraft loads a persistent system tray icon
  2. Press your hotkey (default: backtick ) - A rising cue confirms recording and a click-through REC` timer remains visible while the microphone is live. After one minute it can highlight Still recording as a silent reminder.
  3. Press your hotkey again - A lower falling cue confirms recording has stopped; the floating indicator then shows transcription and cleanup progress, keeps the completed status visible for five seconds, and fades away
  4. Text appears - Transcribed text is automatically pasted at your cursor location, followed by a distinct completion chime
  5. Use tray actions - Click the tray icon to start clipboard dictation, copy the last dictation, open the Control Panel, or quit

You can press the hotkey again and record another dictation while earlier audio is processing. EchoDraft queues complete recordings in order. In insertion mode each result is inserted sequentially into its captured application target; in clipboard mode each result replaces the clipboard when that job completes. A failed job is reported without discarding later queued work.

EchoDraft preserves recognizable speech unless the result is clearly unusable. If a sparse transcript and its retry disagree, the primary transcript is saved in History as needing review instead of being discarded. Insertion mode withholds that uncertain result from automatic paste; clipboard mode keeps a recoverable copy. Empty or punctuation-only output, a detected prompt echo that is too small to trust, and strongly model-generated assistant-style output are still rejected.

On Windows in tap mode, hold Alt while using either configured dictation hotkey to make a Codex prompt. With the current F10 insertion and F9 clipboard bindings, Alt+F10 inserts the finished prompt and Alt+F9 leaves it on the clipboard. Prompt mode uses the same recording and transcription pipeline, then rewrites only for clearer Codex CLI prompting with GPT-5.6 Luna at maximum reasoning effort. It preserves whether the dictation is a standalone request or a contextual follow-up; it does not invent missing context or implementation details. An OpenAI API key is required. History marks these results with a small terminal badge.

Control Panel

  • Access: Click the tray icon, then choose View Control Panel. On Windows, EchoDraft opens it on the current virtual desktop and recreates the window only when Windows cannot safely reuse it there.
  • Configure: Choose between local and cloud processing
  • History: View, search, copy, and delete past transcriptions. Clean again and Make Codex prompt create a linked alternative from the stored raw transcript, leave the original unchanged, and copy the alternative without pasting it. You can flag an item as needing correction for Transcription, Cleanup, Prompt, or Paste/delivery and filter locally by that flag. A terminal badge identifies Codex prompt dictations.
  • To Do: Pending contains mobile memos awaiting action. Archived contains actioned memos and searches every archived row stored on this computer through bounded pages. Both views can copy cleaned or raw text and create eligible copy-only alternatives; Archived does not move items back to Pending.
  • Models: Download and manage local Whisper models
  • Storage Cleanup: Remove downloaded Whisper models from cache to reclaim space
  • Settings: Configure API keys, customize hotkeys, select or test the microphone, preview or adjust dictation sounds, manage permissions, and open Writing for explicit local replacements and fixed application styles. If a selected microphone disconnects or Windows changes its device ID, EchoDraft shows the saved choice as unavailable and temporarily uses the system default. Reselect the microphone to save its current Windows device ID.
  • Developer: Delete logs and transcripts older than 30 days previews one exact cutoff and requires two confirmations before deleting eligible History, every To Do status, linked alternatives/flags, and verified old desktop logs. It excludes captured audio and mobile data.

Mobile To Do inbox

The private Android companion uses Microsoft sign-in and delegated Files.ReadWrite.AppFolder access to publish into its own Apps/EchoDraft Mobile Inbox OneDrive folder; it does not open a network port on the PC or require a custom backend. In Control Panel → To Do, choose the local PC copy of that folder after OneDrive syncs it. The compact 2×1 widget has a standard microphone and a violet microphone-with-terminal button for Codex prompt mode. Standard phone recordings follow the desktop app's selected transcription provider, model, cleanup setting, and generated-title contract. Prompt recordings use the same transcription path followed by GPT-5.6 Luna at maximum reasoning effort; Android does not transcribe either mode locally.

Mobile results appear only in To Do. They do not paste automatically, replace the clipboard, or create a second History item. The tray shows the pending count and offers Copy newest To Do; that action copies only the newest pending memo and never pastes or submits it. Marked items remain locally searchable under Archived. The floating desktop indicator identifies mobile work as To Do, then shows a brief processed or automatic-retry state when processing finishes instead of leaving stale progress visible. While the dictation renderer is ready, EchoDraft checks the selected sync folder every five seconds and removes an uploaded audio/manifest pair only after the cleaned memo has been saved idempotently to To Do. A bounded processing timeout releases an unresponsive renderer request for retry. The folder can therefore be empty during normal operation; completed memo pairs disappear after consumption. The Android companion is intended for private sideloading, not app-store distribution.

Mobile failures produce a bounded, strictly allowlisted, content-free echodraft-mobile-diagnostics.jsonl support file in the OneDrive app folder when Graph is available. A private local copy is retained and retried if OneDrive is temporarily unavailable; the log excludes dictation/audio, exception messages, paths/URIs, account details, credentials, and phone/device identifiers.

See android/README.md for the no-phone build command, private Microsoft registration, later USB installation, OneDrive connection, microphone-permission step, and widget instructions.

Uninstall & Cache Cleanup

  • In-App: Use Settings → General → Local Model Storage → Remove Downloaded Models to clear ~/.cache/echodraft/whisper-models (or %USERPROFILE%\.cache\echodraft\whisper-models on Windows).
  • Windows Uninstall: The NSIS uninstaller automatically deletes the same cache directory.
  • Linux Packages: deb/rpm post-uninstall scripts also remove cached models.
  • macOS: If you uninstall manually, remove ~/Library/Caches or ~/.cache/echodraft/whisper-models if desired.

AI Cleanup

EchoDraft uses a fixed, model-specific cleanup policy built in the trusted main process. Cleanup is an editing transform only: dictated questions and requests remain text and are never answered or executed.

🛡️ Cleanup contract:

  • Adds punctuation, capitalization, quotation marks, and clear formatting
  • Corrects spelling, grammar, obvious recognition artifacts, and unambiguous self-corrections
  • May consolidate or rewrite locally for clarity while preserving every substantive point
  • Keeps questions, requests, caveats, examples, names, numbers, qualifiers, uncertainty, and polarity
  • Preserves model identifiers and file, folder, path, directory, and agent-related tokens instead of guessing a cleaner spelling
  • Adds quotation marks to explicit speech, not around an entire request merely because it reads like a message
  • Requests one JSON object containing a concise content-derived title and the complete cleaned text. EchoDraft only persists the title when that exact contract succeeds.
  • Keeps usable cleaned text when the title envelope is missing or malformed; contract failure alone never causes fallback to the raw dictation.
  • Gives rejected OpenAI BYOK output one model-guided repair on the selected model and effort, using the original transcript, rejected draft, and safety reasons while rechecking the result for fidelity
  • Retries suspicious output conservatively and keeps the original wording if preservation cannot be verified; an independently verified dictionary-backed person-name spelling may still be retained

🤖 AI Provider Options:

  • OpenAI cleanup: GPT-5.6 Terra, GPT-5.6 Luna, and GPT-5.6 Sol
  • OpenAI GPT-5 reasoning: Choose None (recommended default for Luna), Low (more reasoning), or Medium (most thorough) under Settings → AI Text Enhancement. In the current real-audio Luna comparison, None matched Low on usable output quality and was materially faster. A rejected first pass can trigger one model-guided fidelity repair using the same selected model and effort.
  • Anthropic: Claude Opus 4.5, Sonnet 4.5, Haiku 4.5
  • Google: Gemini 2.5 Pro/Flash/Flash-Lite
  • Groq: Ultra-fast Llama and Mixtral inference
  • Local: Qwen, LLaMA, Mistral via llama.cpp

📝 Regular Dictation (for normal text):

  • "This is just normal text I want transcribed"
  • "Meeting notes: John mentioned the quarterly report"
  • "Dear Sarah, thank you for your help"

All dictated text is treated as untrusted content to edit. A dictated instruction is never permission to perform a task.

⌨️ Codex Prompt Dictation:

  • Produces a ready-to-paste prompt without answering or executing it
  • Preserves the requested goal, scope, constraints, uncertainty, and level of detail
  • Preserves contextual follow-ups instead of reporting missing information, adding placeholders, or forcing them to stand alone
  • Does not guess files, commands, architecture, implementation details, acceptance criteria, or permissions that were not dictated
  • Uses GPT-5.6 Luna with maximum reasoning effort, independently of the regular cleanup model and effort settings

Custom Dictionary

Improve transcription accuracy for specific names and technical terms on supported engines:

  1. Access Settings: Open Control Panel → Settings → Custom Dictionary
  2. Add Terms: Enter one word, name, identifier, or technical token per entry
  3. How It Works: EchoDraft sanitizes entries to single lexical terms. For OpenAI transcription, the trusted main process constructs a fixed lexical hint from those terms; supported non-OpenAI engines use their provider-specific hint field. BYOK cleanup receives only the sanitized spellings as trusted lexical data, allowing a tightly bounded final-i recognition variant to use a listed final-e person-name spelling only in clear name grammar while the fidelity guard prevents unrelated substitutions. Unsupported transcription providers transcribe without hints, and managed EchoDraft Cloud does not receive the private dictionary.

Examples of words to add:

  • Uncommon names (e.g., "Sergey", "Xanthe")
  • Technical jargon (e.g., "Kubernetes", "OAuth")
  • Brand names (e.g., "EchoDraft", "whisper.cpp")
  • Domain-specific terms (e.g., "amortization", "polymerase")

Local corrections and application styles

Open Settings → Writing to add an explicit heard phrase → written form correction. These boundary-aware rules are stored locally, remain separate from the speech dictionary, and run before optional cleanup. EchoDraft does not learn rules automatically; each rule can be previewed, edited, disabled, or deleted.

The same page can map an application process name to one fixed Document, Message, or Technical style. Routing uses the process name only. EchoDraft does not capture or send the window title, selection, clipboard contents, screenshot, or surrounding text for this feature. Prompt hotkeys ignore application styles and continue to use GPT-5.6 Luna with maximum reasoning effort.

Processing Options

  • EchoDraft Cloud:
    • Sign in with Google or email — no API keys needed
    • Free plan: 2,000 words/week with 7-day Pro trial for new accounts
    • Pro plan: unlimited transcriptions
  • Bring Your Own Key (BYOK):
    • Use your own API keys from OpenAI, Groq, Mistral, AssemblyAI, or custom endpoints
    • Full control over provider and model selection
  • Local Processing:
    • Install Whisper or NVIDIA Parakeet through the Control Panel
    • Download models: tiny (fastest), base (recommended), small, medium, large (best quality)
    • Complete privacy - audio never leaves your device

Project Structure

echodraft/
├── main.js              # Electron main process & IPC handlers
├── preload.js           # Electron preload script & API bridge
├── setup.js             # First-time setup script
├── package.json         # Dependencies and scripts
├── env.example          # Environment variables template
├── CHANGELOG.md         # Project changelog
├── src/
│   ├── App.jsx          # Main dictation interface
│   ├── main.jsx         # React entry point
│   ├── index.html       # Vite HTML template
│   ├── index.css        # Tailwind CSS v4 configuration
│   ├── vite.config.js   # Vite configuration
│   ├── components/
│   │   ├── ControlPanel.tsx     # Settings and history UI
│   │   ├── OnboardingFlow.tsx   # First-time setup wizard
│   │   ├── SettingsPage.tsx     # Settings interface
│   │   ├── ui/                  # shadcn/ui components
│   │   │   ├── button.tsx
│   │   │   ├── card.tsx
│   │   │   ├── input.tsx
│   │   │   ├── LoadingDots.tsx
│   │   │   ├── Toast.tsx
│   │   │   ├── toggle.tsx
│   │   │   └── tooltip.tsx
│   │   └── lib/
│   │       └── utils.ts         # Utility functions
│   ├── services/
│   │   └── ReasoningService.ts  # Multi-provider AI processing (OpenAI/Anthropic/Gemini)
│   ├── utils/
│   └── components.json          # shadcn/ui configuration
└── assets/                      # App icons and resources

Technology Stack

  • Frontend: React 19, TypeScript, Tailwind CSS v4
  • Build Tool: Vite with optimized Tailwind plugin
  • Desktop: Electron 36 with context isolation
  • UI Components: shadcn/ui with Radix primitives
  • Database: better-sqlite3 for local transcription storage
  • Speech-to-Text: OpenAI Whisper (whisper.cpp) + NVIDIA Parakeet (sherpa-onnx) for local, OpenAI API for cloud
  • Icons: Lucide React for consistent iconography

Development

Agent Quickstart (for contributors / LLM agents)

npm ci
npm run dev

Then (recommended before shipping changes):

npm test
npm run typecheck
npm run lint

Key docs:

  • Debug logging (daily JSONL logs + analysis): see DEBUG.md
  • Windows installer build / in-place upgrade: see Building → Windows Install / In-Place Upgrade (and Building the Windows Installer from WSL)
  • Windows packaged runtime release gate: scripts/gate/windows_release_gate.js (safe non-interactive mode by default; use --allow-foreground-automation only on an idle test desktop)
  • Windows-specific gotchas: WINDOWS_TROUBLESHOOTING.md
  • General troubleshooting: TROUBLESHOOTING.md

Important stability notes (to keep Windows in-place upgrades working):

  • Avoid changing electron-builder.cjs appId / productName without an explicit migration plan.
  • Avoid changing the Windows AppUserModelId (main.js sets this) without understanding taskbar grouping + installer identity implications.

Scripts

  • npm run dev - Start development with hot reload
  • npm run start - Start production build
  • npm run setup - First-time setup (creates .env file)
  • npm run build:renderer - Build the React app only
  • npm run download:whisper-cpp - Download whisper.cpp for the current platform
  • npm run download:whisper-cpp:all - Download whisper.cpp for all platforms
  • npm run download:llama-server - Download llama.cpp server for local LLM inference
  • npm run download:llama-server:all - Download llama.cpp server for all platforms
  • npm run download:sherpa-onnx - Download sherpa-onnx for Parakeet local transcription
  • npm run download:sherpa-onnx:all - Download sherpa-onnx for all platforms
  • npm run compile:native - Compile native helpers (Globe key listener for macOS, key listener for Windows)
  • npm run build - Full package build; signs only when certificates are configured
  • npm run build:mac - macOS package build (distribution requires signing/notarization)
  • npm run build:win - Windows installer/portable build (verify Authenticode before distribution)
  • npm run build:linux - Linux build
  • npm run pack - Build without signing (for personal use)
  • npm run dist - Build and package; signs only when certificates are configured
  • npm run lint - Run ESLint
  • npm run format - Format code with Prettier
  • npm run clean - Clean build artifacts
  • npm run preview - Preview production build
  • npm run android:build - Test, lint, and build the private Android companion (no phone required)
  • npm run android:install - Rebuild and install it on exactly one connected, authorized Android phone

Architecture

The app consists of two main windows:

  1. Main Window: Minimal overlay for dictation controls
  2. Control Panel: Full settings and history interface

Both use the same React codebase but render different components based on URL parameters.

Key Components

  • main.js: Electron main process, IPC handlers, database operations
  • preload.js: Secure bridge between main and renderer processes
  • App.jsx: Main dictation interface with recording controls
  • ControlPanel.tsx: Settings, history, and model management
  • src/helpers/whisper.js: whisper.cpp integration for local processing
  • better-sqlite3: Local database for transcription history

Tailwind CSS v4 Setup

This project uses the latest Tailwind CSS v4 with:

  • CSS-first configuration using @theme directive
  • Vite plugin for optimal performance
  • Custom design tokens for consistent theming
  • Dark mode support with @variant

Building

The build process creates a single executable for your platform:

# Development build
npm run pack

# Production builds
npm run dist           # Current platform
npm run build:mac      # macOS DMG + ZIP
npm run build:win      # Windows NSIS + Portable
npm run build:linux    # AppImage + DEB

Windows Install / In-Place Upgrade

On Windows, npm run build:win produces two .exe files in dist/:

  • EchoDraft Setup <version>.exe - NSIS installer (use this to install, reinstall, or upgrade over the top of an existing installation)
  • EchoDraft <version>.exe - portable build (no installer; runs in-place)

Tip: If you're trying to “reinstall/upgrade”, run the Setup installer (NSIS). The portable .exe won't update an existing installed app.

Security: unsigned Windows builds intentionally disable the in-app automatic updater. Install a locally verified Setup artifact manually; automatic checks, downloads, and installs are enabled only when the build has code signing configured with a pinned publisher.

Building the Windows Installer from WSL

Windows packaging must run on Windows (native modules like better-sqlite3 are platform-specific and scripts/require-windows.js will block WSL/Linux builds).

If you develop in WSL, copy the repo into the Windows filesystem and run the build from Windows PowerShell:

# From WSL (copy into a Windows folder; keep node_modules/dist out of the copy)
rsync -a --delete \
  --exclude ".git" --exclude "node_modules" --exclude "dist" --exclude "resources/bin" \
  ./ /mnt/c/Users/<you>/AppData/Local/Temp/echodraft-winbuild/
# From Windows PowerShell
cd $env:TEMP\echodraft-winbuild
npm ci
npm run build:win

Optionally copy the installer somewhere convenient (e.g. Downloads) for an in-place upgrade:

Copy-Item ".\\dist\\EchoDraft Setup *.exe" "$env:USERPROFILE\\Downloads\\"

Note: build/pack/dist scripts automatically download whisper.cpp, llama-server, and sherpa-onnx for the current platform. For multi-platform packaging from one host, run the :all variants first (npm run download:whisper-cpp:all, npm run download:llama-server:all, npm run download:sherpa-onnx:all).

Configuration

Environment Variables

Create a .env file in the root directory (or use npm run setup):

# OpenAI API Configuration (optional - only needed for cloud processing)
OPENAI_API_KEY=your_openai_api_key_here

# Optional: Customize the Whisper model
WHISPER_MODEL=whisper-1

# Optional: Set language for better transcription accuracy
LANGUAGE=

# Optional: Anthropic API Configuration
ANTHROPIC_API_KEY=your_anthropic_api_key_here

# Optional: Google Gemini API Configuration
GEMINI_API_KEY=your_gemini_api_key_here

# Optional: Groq API Configuration (ultra-fast inference)
GROQ_API_KEY=your_groq_api_key_here

# Optional: Mistral API Configuration (Voxtral transcription)
MISTRAL_API_KEY=your_mistral_api_key_here

# Optional: Debug mode
DEBUG=false

Local Whisper Setup

For local processing, EchoDraft uses OpenAI's Whisper model via whisper.cpp - a high-performance C++ implementation:

  1. Bundled Binary: whisper.cpp is bundled with the app for all platforms
  2. GGML Models: Downloads optimized GGML models on first use to ~/.cache/echodraft/whisper-models/
  3. No Dependencies: No Python or other runtime required

System Fallback: If the bundled binary fails, install via package manager:

From Source: When running locally (not a packaged build), download the binary with npm run download:whisper-cpp so resources/bin/ has your platform executable.

Requirements:

  • Sufficient disk space for models (75MB - 3GB depending on model)

Upgrading from Python-based version: If you previously used the Python-based Whisper, you'll need to re-download models in GGML format. You can safely delete the old Python environment (~/.echodraft/python/) and PyTorch models (~/.cache/whisper/) to reclaim disk space.

Local Parakeet Setup (Alternative)

EchoDraft also supports NVIDIA Parakeet models via sherpa-onnx - a fast alternative to Whisper:

  1. Bundled Binary: sherpa-onnx is bundled with the app for all platforms
  2. INT8 Quantized Models: Efficient CPU inference
  3. Models stored in: ~/.cache/echodraft/parakeet-models/

Available Models:

  • parakeet-tdt-0.6b-v3: Multilingual (25 languages), ~680MB

When to use Parakeet vs Whisper:

  • Parakeet: Best for speed-critical use cases or lower-end hardware
  • Whisper: Best for quality-critical use cases or when you need specific model sizes

Customization

  • Hotkey: Change in the Control Panel (default: backtick `) - fully customizable
  • Tray Status: Click the tray icon for current dictation state, last dictation copy, and Control Panel access
  • Processing Method: Choose local or cloud in Control Panel
  • Whisper Model: Select quality vs speed in Control Panel
  • UI Theme: Edit CSS variables in src/index.css
  • Window Size: Adjust dimensions in main.js
  • Database: Transcriptions stored in user data directory

Contributing

We welcome contributions! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development Guidelines

  • Run npm run lint before committing
  • Follow the existing code style
  • Update documentation as needed
  • Test on your target platform before submitting

Security

EchoDraft is designed with privacy and security in mind:

  • Local Processing Option: Keep your voice data completely private
  • No Analytics: We don't collect any usage data or telemetry
  • Optional Local Debug Logs: You can enable a high-detail debug log that is written locally to disk (never uploaded automatically)
  • Open Source: All code is available for review
  • Secure Storage: API keys are stored securely in your system's keychain/credential manager
  • Minimal Permissions: Only requests necessary permissions (microphone, accessibility)

Troubleshooting

Common Issues

  1. Microphone permissions: Grant permissions in System Preferences/Settings
  2. Accessibility permissions (macOS): Required for automatic text pasting
    • Go to System Settings → Privacy & Security → Accessibility
    • Add EchoDraft and enable the checkbox
    • Use "Fix Permission Issues" in Control Panel if needed
  3. API key errors (cloud processing only): Ensure your OpenAI API key is valid and has credits
    • Set the key through the Control Panel or an environment variable
    • EchoDraft deliberately redacts credentials from diagnostic logs
  4. Local Whisper issues:
    • whisper.cpp is bundled with the app
    • If bundled binary fails, install via brew install whisper-cpp (macOS)
    • Check available disk space for models
  5. Global hotkey conflicts: Change the hotkey in the Control Panel - any key can be used
    • GNOME Wayland: Hotkeys are registered via gsettings; check Settings → Keyboard → Shortcuts for conflicts
  6. Text not pasting:
    • macOS: Check accessibility permissions (System Settings → Privacy & Security → Accessibility)
    • Linux X11: Install xdotool
    • Linux Wayland: Install wtype or ydotool for paste simulation (ensure ydotoold daemon is running)
    • All platforms: Text is always copied to clipboard - use Ctrl+V (Cmd+V on macOS) to paste manually
  7. Panel position: If the panel appears off-screen, restart the app to reset position
  8. Microphone uncertainty: Open Settings → General → Microphone and run the 15-second level test. It starts only when clicked and releases the microphone when stopped, completed, or closed.
  9. Slow cloud transcription or cleanup: After ten seconds EchoDraft shows the elapsed stage time. You can cancel the active request, including supported in-flight cleanup calls and retry delays. Transient network, timeout, rate-limit, and server failures receive at most one sequential retry, and cancelled text is never delivered later.

Debug Logs (Local)

If you need to diagnose lag, missing audio, or truncated transcripts, enable Debug mode in the Control Panel:

  • Control Panel → Developer → Debug mode
  • Logs are written as JSONL (one JSON object per line) to a daily file:
    • Preferred: logs/echodraft-debug-YYYY-MM-DD.jsonl next to the installed EchoDraft.exe
    • Fallback: the app’s userData/logs directory (if the install directory isn’t writable)
  • Use Open Logs Folder in the Developer section to jump to the current log location.
  • Use Delete Diagnostic Data to permanently remove EchoDraft daily logs and rolling input-audio captures from its verified log locations. Source audio is retained for completed desktop and mobile dictations even when debug logging is off. Turn debug mode off first if you do not want a fresh log created.
  • Use Delete logs and transcripts older than 30 days for the separate age-based flow. It uses two cancel-default confirmations and deletes only previewed History, every To Do status, their linked alternatives/flags, and verified desktop JSONL logs strictly older than one captured UTC cutoff. It never deletes captured audio or mobile data.

For full details (enable/disable options, log format, and what gets captured), see DEBUG.md.

Log analysis tips

  • The first line of each file is a type: "header" record (system/app details + settings snapshot placeholders). Most queries should filter it out.
  • When debug mode is enabled, the renderer logs a Renderer settings snapshot and traces localStorage mutations (localStorage.setItem/removeItem/clear) with basic redaction heuristics.
  • Follow a single dictation end-to-end via meta.sessionId and/or meta.jobId (these appear on hotkey/dictation/paste/history events).
  • Useful scope values to filter by: hotkey, dictation, audio, streaming, transcription, reasoning, paste, history, settings, performance, pipeline.
  • To separate “transcription vs cleanup” issues:
    • Compare rawText vs cleanedText in trace logs (e.g. Transcription result text, Streaming transcript text, Dictation transcript text).
    • In History, raw_text is stored separately and shown under “Details” when different.
    • When EchoDraft Cloud cleanup runs, meta.source is tagged as echodraft-reasoned (or echodraft-byok-reasoned).

If you have jq installed, a few quick recipes:

# 1) Show warnings/errors (good first-pass triage)
jq -r 'select(.type!="header") | select(.level=="warn" or .level=="error") | [.ts,.scope,.message] | @tsv' \
  logs/echodraft-debug-YYYY-MM-DD.jsonl

# 2) Hotkey → recording latency (helps diagnose “delay before recording starts”)
jq -r 'select(.message=="Dictation recording started") | [.ts,.meta.hotkeyToRecordingMs,.meta.method] | @tsv' \
  logs/echodraft-debug-YYYY-MM-DD.jsonl

# 3) Pipeline timings (helps spot truncation, slow cleanup, etc.)
jq -r 'select(.message=="Pipeline timing") | [.ts,.meta.mode,.meta.model,.meta.roundTripDurationMs,.meta.transcriptionProcessingDurationMs,.meta.reasoningProcessingDurationMs] | @tsv' \
  logs/echodraft-debug-YYYY-MM-DD.jsonl

Warning: Debug logs may contain transcribed text and other sensitive data. Share only with trusted support.

Getting Help

  • Check the Issues page
  • Review the console logs for debugging information
  • For local processing: Ensure whisper.cpp is accessible and models are downloaded
  • For cloud processing: Verify your OpenAI API key and billing status
  • Check the Control Panel for system status and diagnostics

Performance Tips

  • Local Processing: Use "base" model for best balance of speed and accuracy
  • Cloud Processing: Generally faster but requires internet connection
  • Model Selection: tiny (fastest) → base (recommended) → small → medium → large (best quality)
  • Permissions: Ensure all required permissions are granted for smooth operation

FAQ

Q: Is EchoDraft really free? A: Yes! EchoDraft is open source and free to use. The free plan includes 2,000 words/week of cloud transcription, and local processing is completely free with no limits. Pro plan ($9/month) offers unlimited cloud transcription.

Q: Which processing method should I use? A: Use local processing for privacy and offline use. Use cloud processing for speed and convenience.

Q: Can I use this commercially? A: Yes! The MIT license allows commercial use.

Q: How do I change the hotkey? A: Open the Control Panel (right-click tray icon) and go to Settings. You can set any key as your hotkey.

Q: Is my data secure? A: With local processing, your audio never leaves your device. With cloud processing, audio is sent to OpenAI's servers (see their privacy policy).

Q: What languages are supported? A: EchoDraft supports 58 languages including English, Spanish, French, German, Chinese, Japanese, and more. Set your preferred language in the .env file or use auto-detect.

Project Status

EchoDraft is actively maintained and ready for production use. Current version: 1.4.10

  • ✅ Core functionality complete
  • ✅ Cross-platform support (macOS, Windows, Linux)
  • ✅ EchoDraft Cloud with account system and usage tracking
  • ✅ Free and Pro plans with Stripe billing
  • ✅ Local and cloud processing
  • ✅ Multi-provider AI (OpenAI, Anthropic, Gemini, Groq, Mistral, Local)
  • ✅ Compound hotkey support
  • ✅ Windows Push-to-Talk with native key listener
  • ✅ Custom dictionary for improved transcription accuracy
  • ✅ NVIDIA Parakeet support via sherpa-onnx
  • ✅ GNOME Wayland native global shortcuts

Acknowledgments

  • OpenAI Whisper - The speech recognition model that powers both local and cloud transcription
  • whisper.cpp - High-performance C++ implementation of Whisper for local processing
  • NVIDIA Parakeet - Fast ASR model for efficient local transcription
  • sherpa-onnx - Cross-platform ONNX runtime for Parakeet model inference
  • Electron - Cross-platform desktop application framework
  • React - UI component library
  • shadcn/ui - Beautiful UI components built on Radix primitives
  • llama.cpp - Local LLM inference for AI-powered text processing

About

Voice-to-text dictation app with local (Nvidia Parakeet/Whisper) and cloud models (BYOK). Privacy-first and available cross-platform.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0