Skip to main content

Database Schema

OpenWhispr uses better-sqlite3 for local data storage. The database is located in the app’s user data directory:
  • macOS: ~/Library/Application Support/OpenWhispr/transcriptions.db
  • Windows: %APPDATA%\OpenWhispr\transcriptions.db
  • Linux: ~/.config/OpenWhispr/transcriptions.db

Tables

transcriptions

Stores transcription history.
CREATE TABLE transcriptions (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  text TEXT NOT NULL,
  timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

custom_dictionary

Stores custom vocabulary words for improved transcription accuracy.
CREATE TABLE custom_dictionary (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  word TEXT NOT NULL UNIQUE,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

notes

Stores notes with optional AI enhancement.
CREATE TABLE notes (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  title TEXT NOT NULL DEFAULT 'Untitled Note',
  content TEXT NOT NULL DEFAULT '',
  note_type TEXT NOT NULL DEFAULT 'personal',
  source_file TEXT,
  audio_duration_seconds REAL,
  enhanced_content TEXT,
  enhancement_prompt TEXT,
  enhanced_at_content_hash TEXT,
  folder_id INTEGER REFERENCES folders(id),
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

folders

Stores note organization folders.
CREATE TABLE folders (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL UNIQUE,
  is_default INTEGER NOT NULL DEFAULT 0,
  sort_order INTEGER NOT NULL DEFAULT 0,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Transcription History

window.electronAPI.saveTranscription()

Save a transcription to the database.
text
string
required
The transcribed text to save
success
boolean
Whether the transcription was saved successfully
id
number
The ID of the newly created transcription record
transcription
object
The full transcription record (id, text, timestamp, created_at)

Example

const result = await window.electronAPI.saveTranscription("Hello world");

if (result.success) {
  console.log("Saved transcription ID:", result.id);
  console.log("Timestamp:", result.transcription.timestamp);
}

window.electronAPI.getTranscriptions()

Retrieve transcription history.
limit
number
default:"50"
Maximum number of transcriptions to retrieve
transcriptions
array
Array of transcription objects, ordered by most recent first

Example

const history = await window.electronAPI.getTranscriptions(100);

history.forEach(t => {
  console.log(`[${t.timestamp}] ${t.text}`);
});

window.electronAPI.deleteTranscription()

Delete a specific transcription.
id
number
required
The ID of the transcription to delete
success
boolean
Whether the transcription was deleted successfully
id
number
The ID of the deleted transcription
await window.electronAPI.deleteTranscription(123);

window.electronAPI.clearTranscriptions()

Delete all transcriptions.
success
boolean
Whether all transcriptions were cleared
cleared
number
Number of transcriptions deleted
const result = await window.electronAPI.clearTranscriptions();
console.log(`Deleted ${result.cleared} transcriptions`);

Custom Dictionary

window.electronAPI.getDictionary()

Get all custom dictionary words.
words
array
Array of custom vocabulary words (strings)
const words = await window.electronAPI.getDictionary();
console.log("Custom words:", words);
// ["OpenWhispr", "API", "IPC", "Parakeet"]

window.electronAPI.setDictionary()

Replace the entire custom dictionary.
words
array
required
Array of words to save (strings)
success
boolean
Whether the dictionary was updated successfully

Example

const customWords = ["OpenWhispr", "Anthropic", "Claude", "GPT-5"];

const result = await window.electronAPI.setDictionary(customWords);

if (result.success) {
  console.log("Dictionary updated");
}
Custom dictionary words are passed as the initialPrompt parameter to Whisper, improving recognition of uncommon words, names, and technical terms.

window.electronAPI.undoLearnedCorrections()

Remove auto-learned corrections from the dictionary.
words
array
required
Array of words to remove (strings)
success
boolean
Whether the words were removed successfully
// Remove auto-learned words
await window.electronAPI.undoLearnedCorrections(["misheardword"]);

Notes

window.electronAPI.saveNote()

Create a new note.
title
string
required
Note title
content
string
required
Note content (Markdown supported)
noteType
string
default:"personal"
Note type: "personal", "meeting", "transcription"
sourceFile
string
Path to source audio file (if transcribed from file)
audioDuration
number
Duration of audio in seconds
folderId
number
ID of the folder to save the note in
success
boolean
Whether the note was saved successfully
note
object
The full note record

Example

const result = await window.electronAPI.saveNote(
  "Meeting Notes",
  "Discussed Q1 roadmap and feature priorities.",
  "meeting",
  null,
  null,
  2 // folder ID
);

if (result.success) {
  console.log("Note ID:", result.note.id);
}

window.electronAPI.getNote()

Get a specific note by ID.
id
number
required
Note ID
note
object | null
Note object, or null if not found
const note = await window.electronAPI.getNote(5);

if (note) {
  console.log("Title:", note.title);
  console.log("Content:", note.content);
}

window.electronAPI.getNotes()

Get notes filtered by type and/or folder.
noteType
string
Filter by note type (optional)
limit
number
default:"100"
Maximum number of notes to retrieve
folderId
number
Filter by folder ID (optional)
notes
array
Array of note objects, ordered by most recently updated

Example

// Get all notes in folder 2
const folderNotes = await window.electronAPI.getNotes(null, 100, 2);

// Get meeting notes only
const meetingNotes = await window.electronAPI.getNotes("meeting", 50);

// Get all notes
const allNotes = await window.electronAPI.getNotes(null, 100);

window.electronAPI.updateNote()

Update an existing note.
id
number
required
Note ID
updates
object
required
success
boolean
Whether the note was updated successfully
note
object
The updated note record

Example

const result = await window.electronAPI.updateNote(5, {
  title: "Updated Meeting Notes",
  content: "Revised content...",
  folder_id: 3
});

if (result.success) {
  console.log("Note updated:", result.note.updated_at);
}

window.electronAPI.deleteNote()

Delete a note.
id
number
required
Note ID
success
boolean
Whether the note was deleted successfully
await window.electronAPI.deleteNote(5);

window.electronAPI.exportNote()

Export a note to a file.
noteId
number
required
Note ID
format
string
required
Export format: "md" (Markdown) or "txt" (plain text)
success
boolean
Whether the note was exported successfully
error
string
Error message if failed
const result = await window.electronAPI.exportNote(5, "md");

if (result.success) {
  console.log("Note exported");
}

Folders

window.electronAPI.getFolders()

Get all folders.
folders
array
Array of folder objects, ordered by sort_order
const folders = await window.electronAPI.getFolders();

folders.forEach(f => {
  console.log(`${f.name} (${f.is_default ? 'default' : 'custom'})`);
});

window.electronAPI.createFolder()

Create a new folder.
name
string
required
Folder name (must be unique)
success
boolean
Whether the folder was created successfully
folder
object
The newly created folder record
error
string
Error message if failed (e.g., “A folder with that name already exists”)
const result = await window.electronAPI.createFolder("Projects");

if (result.success) {
  console.log("Folder ID:", result.folder.id);
}

window.electronAPI.deleteFolder()

Delete a folder (notes are moved to the default “Personal” folder).
id
number
required
Folder ID
success
boolean
Whether the folder was deleted successfully
error
string
Error message if failed (e.g., “Cannot delete default folders”)
await window.electronAPI.deleteFolder(3);

window.electronAPI.renameFolder()

Rename a folder.
id
number
required
Folder ID
name
string
required
New folder name (must be unique)
success
boolean
Whether the folder was renamed successfully
folder
object
The updated folder record
error
string
Error message if failed
const result = await window.electronAPI.renameFolder(3, "Work Projects");

if (result.success) {
  console.log("Folder renamed:", result.folder.name);
}

window.electronAPI.getFolderNoteCounts()

Get note counts for each folder.
counts
array
Array of objects with folder_id and count properties
const counts = await window.electronAPI.getFolderNoteCounts();

counts.forEach(c => {
  console.log(`Folder ${c.folder_id}: ${c.count} notes`);
});

Real-Time Events

Listen for database changes in real-time:

window.electronAPI.onTranscriptionAdded()

const cleanup = window.electronAPI.onTranscriptionAdded((transcription) => {
  console.log("New transcription:", transcription);
  // Update UI
});

// Clean up when component unmounts
cleanup();

window.electronAPI.onTranscriptionDeleted()

window.electronAPI.onTranscriptionDeleted(({ id }) => {
  console.log("Transcription deleted:", id);
});

window.electronAPI.onTranscriptionsCleared()

window.electronAPI.onTranscriptionsCleared(({ cleared }) => {
  console.log(`${cleared} transcriptions cleared`);
});

window.electronAPI.onNoteAdded()

window.electronAPI.onNoteAdded((note) => {
  console.log("New note:", note.title);
});

window.electronAPI.onNoteUpdated()

window.electronAPI.onNoteUpdated((note) => {
  console.log("Note updated:", note.id);
});

window.electronAPI.onNoteDeleted()

window.electronAPI.onNoteDeleted(({ id }) => {
  console.log("Note deleted:", id);
});

window.electronAPI.onDictionaryUpdated()

window.electronAPI.onDictionaryUpdated((words) => {
  console.log("Dictionary updated:", words);
});

Build docs developers (and LLMs) love