Eloquent Notes

A lightweight, system-tray-centric utility for Linux inspired by Google Eloquent. Record quick dictations, clean and structure them locally with Gemma 4, and write them directly to Obsidian.

View on GitHub

What is Eloquent Notes?

Eloquent Notes is a system tray daemon designed for Linux desktops that allows you to instantly record dictations without opening a heavy application. It captures your microphone input, runs it through a local LLM via Ollama to perform speech-to-text cleanup and structural formatting, and saves the result directly as Markdown notes inside your Obsidian vault.

With absolute privacy and zero-latency cloud dependencies, your recordings and transcripts never leave your computer.

Features

🔘 System Tray UX

Minimal tray icon interface. Click once to start recording, click again to finish and process. Zero window clutter.

🔒 100% Offline & Private

No telemetry, no external APIs. Local transcription and text refinement powered by Ollama and Gemma 4.

🎨 Dynamic Indicators

Icon changes color dynamically: Gray (Idle), Red (Recording), Orange (Processing via LLM).

💎 Obsidian Integration

Appends formatted notes to your daily journals or generates individual files with tags and frontmatter metadata.

⚙️ Hot-Reload Config

Reload your prompts and settings on-the-fly from the system tray menu without restarting the service.

📝 Custom Prompts

Fully customize the system instructions and output schemas using simple Markdown files.

Architectural Overview

Eloquent Notes utilizes PyQt6, sounddevice for in-memory recording, and asynchronous worker threads to ensure your desktop environment remains fast and responsive.

graph TD
    A[PyQt6 System Tray Event Loop] -->|Left Click / Menu| B{Recording State?}
    B -->|IDLE| C[Start Recording]
    B -->|RECORDING| D[Stop & Process]
    
    C -->|Background Thread| E[Preload Gemma 4 in Ollama]
    C -->|sounddevice| F[Capture Mic Input to Queue]
    
    D -->|sounddevice| G[Stop Capture & Convert to WAV in Memory]
    D -->|Background Thread| H[Send Base64 Audio to Ollama]
    
    H -->|Cleaned JSON Response| I{Empty Note?}
    I -->|No| J[Save to Obsidian Vault]
    I -->|Yes| K[Show Notification]
    
    J --> L[Show Success Notification]
    K --> M[Restore Gray Icon]
    L --> M
                    

Key Technical Details

  • In-Memory Processing: Audio is processed directly in memory as 16-bit PCM WAV bytes (using io.BytesIO). No temporary files are written to disk, preserving privacy and hardware lifespan.
  • Non-Blocking Threads: Both the model preloading and Ollama requests run in QThreads. The UI never freezes or stutters during execution.
  • Dynamic Icon Generation: State icons are drawn dynamically at runtime using Pillow (PIL) and converted to QIcons. No external image assets needed.
  • Structured JSON Outputs: Restrictive schema formats ensure Ollama returns clean JSON with empty and text flags for robust parsing.

Prerequisites

Before installing, make sure you have the following requirements satisfied:

1. Ollama & Gemma 4 Model

Ensure Ollama is running and download the default model:

ollama pull gemma4:12b-it-qat

2. System Dependencies

Install PortAudio (required for audio capture) and a desktop notification service:

# Ubuntu / Debian / Pop!_OS:
sudo apt install libportaudio2

Installation

Option A: Using uv or pipx (Recommended)

Install directly from the remote repository:

# Using uv
uv tool install git+https://github.com/arrase/eloquent-notes.git

# Or using pipx
pipx install git+https://github.com/arrase/eloquent-notes.git

Option B: Local Development Clone

git clone https://github.com/arrase/eloquent-notes.git
cd eloquent-notes

# Setup virtual environment
python3 -m venv .venv
source .venv/bin/activate
pip install -e .

Configuration

Upon your first run, Eloquent Notes initializes configuration settings at ~/.config/eloquent-notes/.

Config file (config.yaml)

obsidian:
  vault_path: "~/Obsidian"     # Absolute or relative path to Obsidian Vault
  folder: "Dictations"         # Folder name inside vault
  daily_notes: true            # Append dictations to daily note files (YYYY-MM-DD.md)

ai:
  ollama_url: "http://localhost:11434"
  model: "gemma4:12b-it-qat"
  context_length: 10000        # Context length limit
  keep_alive: "0"              # Model VRAM unload timer
  preload_keep_alive: "5m"     # Keeps loaded during recording

audio:
  sample_rate: 16000           # Sample rate (16kHz is ideal)
  channels: 1                  # Mono channel
  beep_frequency: 440          # Beep sound cue (Hz)
  beep_duration: 0.1           # Beep duration (seconds)
  beep_enabled: true           # Enable/disable audio cues (beeps)

Customizable Prompts

Tweak how notes are parsed and formatted:

  • ~/.config/eloquent-notes/prompts/system_prompt.md (Controls formatting, cleaning fill words, structuring)
  • ~/.config/eloquent-notes/prompts/user_prompt.md (Sends context about date, current vault state)

Usage

Start the daemon in the background:

eloquent-notes &

Control & Autostart

  • Start/Stop: Left-click the gray system tray microphone icon to trigger recording.
  • Autostart on boot: Run eloquent-notes install-autostart to automatically register the service with your desktop environment.