KillerNotes Download
Technical

How the notepad actually works: storage, search, encryption, and the sharing formats.

Architecture

KillerNotes is a native Windows app written in C# and WPF on .NET Framework 4.8 (x64). There is no web view wrapping a JavaScript app and no runtime to install on Windows 10/11 - it is the same stack as the rest of the KillerTools family, sharing the KillerUI chrome: custom title bar, thirteen live-switchable themes with accent colors, film grain, and the family status bar.

The editor is a WPF RichTextBox working on a real FlowDocument, which is what makes inline images and true tables first-class citizens rather than attachments. Everything else - search, storage, encryption, sharing - lives underneath it in a SQLite database.

A database, for the layman

"SQLite database" sounds heavier than it is, so here is the plain-English version. A relational database stores data in tables that look a lot like spreadsheets: each row is one thing (one note, one tag), and each column is one fact about it (its title, its created date). "Relational" just means the tables can point at each other - a small linking table records that note 12 carries tag 3, and that is the entire trick behind tags, groups, and search staying in agreement with each other.

SQL is the language for asking the tables questions ("every note tagged Urgent, newest first") and for changing them. The app writes those queries; you never see one.

SQLite is the engine that runs the queries - and unlike the databases behind websites, it is not a server. Nothing runs in the background and there is nothing extra to install: the engine is a library compiled into KillerNotes.exe, and the entire database is one ordinary file on disk. Copy the file and you have copied every note in it.

Why bother, instead of a folder of .txt files? Three things a folder cannot do:

  • Transactions - every save happens completely or not at all. Power loss mid-save leaves the previous version intact, never half a note.
  • Indexes - like the index in the back of a book: finding "firewall" means jumping straight to it, not opening every note and reading it. That is what keeps search instant at thousands of notes.
  • One file - notes, images, tags, groups, and the search index travel together, which is what makes whole-notepad encryption and one-file sharing possible at all.

SQLite is the most widely deployed database in the world - it is in every phone, browser, and car. Your notes are in reliable company. The sections below get into the specifics.

Storage

Notes live in a single SQLite database per notepad, stored under %APPDATA%\KillerNotes by default - the data folder is configurable from Manage databases. Each note row keeps three representations of the same content:

  • Title and metadata - creation and modification timestamps, used for the sidebar and sorting.
  • A XamlPackage blob - the full rich content. XamlPackage is WPF's container format for FlowDocuments: formatting, embedded images, and tables all round-trip through the database byte-perfect. Pasted screenshots are re-encoded to PNG on the way in so they serialize reliably.
  • A plain-text shadow copy - extracted on every save and fed to the search index, so search never has to parse rich content.

A fourth column, format, says which of two content types the row is: rich text or markdown. Rich text is the default and every note written before 1.3.0 is one. A markdown note stores its source instead - what you typed, line for line - but still inside a XamlPackage container rather than as raw UTF-8 bytes. That wrapper is deliberate: every release before 1.3.0 reads any blob as a XamlPackage, so raw bytes in a shared .kndb or .knote would throw during startup on the receiving machine, before its window was usable. Wrapped, the same note opens in an older build as ordinary rich text showing its markdown source. The cost is a fixed floor of roughly 1.6 KB per markdown note; past that size the package deflates and comes out smaller than the raw source.

The editor control is the same RichTextBox for both types, with a markdown note loaded as one zero-margin paragraph per line. Everything built on the FlowDocument - find, replace, dictation, caret and scroll persistence, word wrap - therefore works on both without forking. What differs is what a markdown note will accept: images, tables, sketches and embedded recordings are refused at the four insertion points with a status-bar line, because the plain-text projection cannot carry them and they would vanish at the next save. Character formatting is deliberately not blocked - bold loses its weight on save but keeps every character, and refusing the keystroke would surprise more than the formatting quietly not sticking.

Sketches and dictation recordings sit in side tables keyed to the note rather than inside its XamlPackage. Audio is far larger than the note that references it, and inlining it would make every load and save of that note carry it; the note keeps only a small marker. Both are encrypted with the rest of the database when a password is set.

Editor WPF RichTextBox FlowDocument images + tables inline autosave 2s pause note switch alt-tab / close One note, three forms title + timestamps XamlPackage blob (rich) plain-text shadow copy SQLCipher AES-256 (optional) notes.db (SQLite) notes table ⇅ external-content triggers FTS5 full-text index %APPDATA%\KillerNotes .knote one torn-off note .kndb whole notepad .txt .rtf .html plain exports
The life of a note: the editor commits every change into one SQLite file, the search index stays in sync by trigger, encryption wraps the whole file, and shares tear off from there.Click the diagram to enlarge.

Autosave

There is no Save button to forget. A save commits 2 seconds after you stop typing, plus immediately on note switch, on alt-tab away, and on close. Ctrl+S exists for peace of mind, but it is just "commit now" - the same write the timer would have made.

Encryption

Password protection is whole-database encryption with SQLCipher (AES-256), not an application-level gate. When a password is set, every byte of the file is encrypted at rest - notes, images, the search index, the metadata, all of it. A KillerNotes database with a password is unreadable in any SQLite tool without the key.

Setting, changing, or removing the password rebuilds the database through SQLCipher's export path into a fresh file, then atomically swaps it in. There is no plaintext temp copy of an encrypted database left behind.

The honest fine print

  • A database with no password set is a normal SQLite file - encryption is opt-in per database, one click on the title-bar lock.
  • There is no recovery back door. If you forget the password, the unlock screen offers a fresh start and archives the locked file (kept on disk, unlockable later if the password comes back to you) - but the encrypted data itself is unrecoverable by design.
  • Drag-out shares are unencrypted by design (there is no sane way to prompt for a password mid-drag). Use "Share note..." for a protected copy.

Sharing formats

Sharing follows the notepad metaphor: tear off a sheet, or hand over the whole pad.

  • .knote - a single shared note. Under the hood it is literally a one-note KillerNotes database, optionally SQLCipher-encrypted with its own share password. The recipient double-clicks it and the note imports into their current notepad (prompting for the password if one was set).
  • .kndb - a whole database. Its encryption travels with it: if the notepad had a password, the recipient needs it. Double-clicking adds it to the data folder and switches to it; the previous notepad stays available in Manage databases.

Both extensions register per-user (HKCU only - no admin rights) with their own icons. Dragging a note out of the sidebar uses the standard shell file-drop mechanism, so Teams, Outlook, and Explorer all accept it like a real file, because it is one.

The deliberately avoided extension: .kdb belongs to KeePass, and a tech's file manager should never confuse the two.

Import & export

In

Ctrl+O or drop files anywhere sensible: .txt / .log / .md import as text notes, .rtf loads natively with formatting intact, images land inline, and .html / .htm import as source - which the preview pane then renders, same as the markdown story: source in the editor, preview to view. Each file becomes its own note titled by its filename.

Out

Any note exports as plain text, as .rtf (WordPad/Word-compatible, images included), or as a standalone theme-styled HTML page built by a purpose-built FlowDocument-to-HTML converter: paragraphs, lists, tables, character formatting, colors, and images embedded as base64 data URIs - one self-contained file.

Vault export

The whole database also exports as a folder of .md files. Groups become nested subfolders, and each file opens with a short block listing the title, tags, and created and modified times - editors that do not recognize it simply show it as text at the top rather than mangling the note. Titles become filenames, with anything Windows will not accept cleaned up and duplicates given a number. Everything lands in a subfolder named after the open database, so exporting two notepads side by side cannot merge them.

Rich-text notes are converted on the way out, so the folder is the whole notepad rather than only the notes that were already markdown. That conversion is lossy in the ways the convert dialog names - tables, images, colored text - but nothing in the database is modified: this writes files and touches no note. A single unreadable note is skipped and counted rather than aborting the run.

It is deliberately one-way and on demand rather than a live sync of a watched folder. Sync means conflict resolution, file-watcher races, and partial writes from other editors, and it would leave a permanent plaintext copy of an encrypted database on disk - which contradicts the reason the database is encrypted at all. Export is explicit, so the user chooses the moment the plaintext exists.

Converting between formats

The notes context menu converts one note at a time in either direction. Rich to markdown is lossy, so the confirmation names what will not survive before anything is rewritten; markdown to rich loses nothing. Headings are not reverse-engineered from font size on the way out - a large bold paragraph might be a heading or might be a large bold paragraph, and guessing wrong rewrites the user's document. Hyperlinks arriving from markdown are held to the same three schemes the editor allows anywhere else, since a markdown file is untrusted input once it can arrive by import or from a vault folder.

Either direction is a single app-level undo entry that restores the original bytes rather than converting back. A round trip through the other format is lossy, so re-converting would hand back something subtly different from what was there.

Preview

Notes that look like markdown or HTML get a preview toggle. Markdown renders through Markdig with raw HTML disabled; HTML notes are defused before display - scripts, event handlers, frames, and javascript: URLs are stripped. The preview is a viewer, never a place where pasted content gets to run.

Dictation & audio

Recording and playback go through winmm, the waveIn and waveOut APIs that ship with Windows. Deliberately not WPF's MediaPlayer, which routes through the Windows Media Player components and fails outright on N editions, on Server, and anywhere the Media Feature Pack is absent - an app that records its own audio should not need a media stack to play it back. Capture is 16 kHz mono 16-bit PCM: what speech recognition wants, and only about 32 KB per second.

Storage format

Recordings are stored as FLAC (libFLAC, BSD-3-Clause) - lossless and roughly half the size of WAV. Lossless is the point rather than a nicety: slicing a recording and saving it again is bit-identical every time, so editing the same take repeatedly costs nothing. MP3 (libmp3lame) is offered on export only, where the copy is one-way and universal playability is what matters; storing MP3 would mean every edit was a decode and re-encode, compounding generation loss. The format is detected per recording from its first four bytes, so recordings made before FLAC keep working with no conversion pass.

Speech recognition

Transcription uses whisper.cpp (MIT) running locally. It replaced System.Speech, which is SAPI's desktop dictation engine - a command-and-control model from the Windows 7 era that was not misconfigured but simply at its ceiling, producing confident nonsense on unfamiliar words rather than admitting uncertainty. System.Speech remains as the fallback when no model is installed.

The whisper natives are about 1.3 MB and ship inside the exe. The model is 75 to 466 MB, so it is downloaded on demand from whisper.cpp's own repository, into your local app data, after you pick a size. Nothing is downloaded without being asked, and nothing is uploaded at any point - the audio never leaves the machine.

Three models are offered. The chooser names the file each one downloads, so a copy on disk can always be identified and checked against upstream:

ChoiceFileSizeNotes
Fastggml-tiny.en.bin75 MBFastest. A clear step up from Windows dictation, but weaker on names and technical terms.
Recommendedggml-base.en.bin142 MBThe usual choice. Accurate enough to correct rather than rewrite, and quick on most machines.
Most accurateggml-small.en.bin466 MBMost accurate of the three. Noticeably slower on an older laptop.

All three are the English-only (.en) builds, pulled from huggingface.co/ggerganov/whisper.cpp - whisper.cpp's own repository, not a mirror - and written to %LOCALAPPDATA%\KillerNotes\native\<version>\models. When more than one is present the largest wins. Delete a file to reclaim the space; the chooser reopens from the right-click menu on the microphone in the sidebar rail, which is also the only way to change model after the first prompt.

All three audio natives are cross-compiled from their upstream release tarballs rather than taken from a mirror; the tarballs, hashes and exact build commands are in the source tree, and LAME's LGPL source is attached to every release.

Editor tools

Syntax highlighting

Toggled per note with Ctrl+Shift+E. The highlighter recognizes sixteen languages - PowerShell, Python, SQL, Bash, C#, JavaScript, TypeScript, CSS, HTML, XAML, XML, Vue, JSON, YAML, Markdown and plain - and detection runs per paragraph rather than per note. That is the design decision worth knowing: each block is sniffed on its own, so a scratch note holding a PowerShell one-liner, a SQL query and a chunk of YAML colors all three correctly without a language picker anywhere in the UI. Lines with no giveaway tokens of their own - a bare closing brace, base.OnStartup(e); - inherit the language of the code block above them, so pasted multi-line code colors whole; a prose line ends the block.

Highlighting is viewport-scoped and incremental: only the paragraphs on or near the screen are tokenized, only when their text has changed, and pathological input is fenced by per-paragraph size caps and regex timeouts - a 6000-line pasted script stays typeable and scrollable.

Coloring is applied as TextEffects over the existing runs, so it never touches the stored document - the toggle state rides the note as a tag and the text itself is unchanged. Turning it off restores the original brushes exactly.

SketchPad

A modeless drawing companion on F7 (or Ctrl+Shift+D): pen, line, arrow, rectangle, ellipse, polygon, paint bucket, text labels and an eraser, with per-object color, width and opacity. It stays open beside the note rather than blocking it, so you can draw and type in turn.

Drawings are kept as a vector object list, not just a bitmap. "Print to note" flattens the strokes to an image at the caret and stores the object list alongside it in a side table keyed to the note, so double-clicking that image reopens the original strokes for editing - the picture in the note and the editable drawing behind it stay linked. The paint bucket is a genuine raster flood fill of the rasterized strokes, so an unclosed shape leaks to the canvas edge exactly as it would in MS Paint.

Killculator

A calculator docked in the row beneath the notes list, opened with F9. It is a themed WPF control rather than a shell-out to calc.exe, so it follows the palette and the keyboard. Ctrl+Enter prints the current result into the note; Ctrl+Shift+Enter prints the whole running equation, which is the one that matters when the note has to show the working rather than the answer.

Spell check

Per note, off by default (Ctrl+Shift+P), using Windows' own spell checking. WPF's checker walks the whole document on the UI thread, so notes over 50,000 characters decline the toggle with a status message rather than hanging the app - a pasted script is not what spell check is for anyway.

Floating placement

Images and recordings can be dragged out of the text flow to float, with text wrapping down the side. The mechanism is a FlowDocument Floater, chosen after Figure failed twice: Figure is the element that carries offsets and WrapDirection.Both, but an editable RichTextBox implements only a subset of FlowDocument layout and ignores both. Floater is the part it does implement properly. A Floater has no offset of its own, so horizontal position is a margin snapped to a twelve-column grid - twelve because it divides cleanly by 2, 3, 4 and 6 - and vertical position is which paragraph the object is anchored in, since a Floater reserves its column from its anchor downward. Dragging re-homes the anchor live, and the text lines are themselves the vertical grid.

Localization

The interface ships in twelve languages: English, Bengali, Czech, German, Spanish, French, Hungarian, Japanese, Polish, Turkish, Simplified Chinese and Traditional Chinese. Switching is live - no restart, no relaunch - because every string is a DynamicResource lookup against a merged ResourceDictionary that is swapped in place, the same mechanism the themes use.

Translation covers the whole surface, not just the menus: dialogs, tooltips, context menus, the status bar, the keyboard-shortcut overlay and its visual keyboard map. The shortcut keycaps stay in English on purpose - a key is a physical thing, and translating "Ctrl" helps nobody - while their descriptions are translated.

Each locale is one XAML file in Strings/, so adding a language means adding a file and an entry to the picker, with no code change. Missing keys fall back to en-US rather than rendering blank, so a partial translation degrades to English instead of breaking the layout.

Privacy

Everything runs on your machine. Notes never leave your disk unless you export or share them yourself. There is no account, no cloud sync, no telemetry, and no ads. The only network requests the app ever makes are to GitHub, both from the About panel: a version check when you open it, and the release download itself if you choose to update.

Distribution

KillerNotes ships as a single signed exe - about 8.5 MB with every dependency embedded, including the SQLCipher engine. No installer is required and there is no folder of DLLs: download, double-click, take notes. The exe is Authenticode-signed and timestamped, so Windows shows a verified publisher instead of an unknown-publisher warning, and the About panel shows the certificate thumbprint plus the exe's SHA-256 to check against the release page.

  • Portable first - run it from anywhere, including a USB stick. Notes live in %APPDATA%\KillerNotes by default, and the data folder is configurable - point it next to the exe and the whole notepad travels with the stick.
  • Optional install - a PORTABLE badge in the status bar offers a one-click per-user install: Start Menu shortcut, optional desktop shortcut, and an Add/Remove Programs entry. No admin rights needed.
  • KillerNotes.exe /silent - unattended machine-wide install to Program Files, made for RMM, winget, and Chocolatey deployment. /uninstall reverses it - and your notes are always kept.
  • Open source - GPLv3. Every release attaches the exact source as KillerNotes-x.y.z-src.zip next to the exe.

Specs

SpecValue
PlatformWindows 10/11, x64
StackC# / WPF on .NET Framework 4.8 (no runtime install on Win 10/11)
StorageSQLite via Microsoft.Data.Sqlite; one database file per notepad in a configurable data folder (default %APPDATA%\KillerNotes)
SearchSQLite FTS5, external-content index, prefix matching as you type
EncryptionSQLCipher (AES-256), whole-database, opt-in per database
Rich contentWPF FlowDocument stored as XamlPackage blobs (images + tables round-trip)
MarkdownMarkdig, advanced extensions, raw HTML disabled
Audiowinmm waveIn/waveOut capture and playback at 16 kHz mono; stored as FLAC, exports to WAV or MP3
Speechwhisper.cpp offline, model downloaded on demand (75-466 MB); System.Speech fallback
Syntax highlighting16 languages, detected per paragraph; applied as TextEffects, stored text unchanged
DrawingSketchPad vector object list, flattened to an image in the note and reopenable for editing
Themes13 (98SE, Black, Blood, Cyanotic, Dark, Decay, Delirium, Ectoplasm, Greed, Light, Malaise, Mourning, Sepulchre), live-switchable with per-theme accents
Languages12 (en, bn, cs, de, es, fr, hu, ja, pl, tr, zh-Hans, zh-Hant), live-switchable, en-US fallback
Share formats.knote (single note), .kndb (whole database), HKCU file associations
Import.txt, .log, .md, .html, .htm, .rtf, png/jpg/jpeg/gif/bmp images
Export.txt, .rtf, self-contained .html; notes also share as .knote
Network useNone, except the About panel's version check and optional self-update download (GitHub)
DistributionSingle signed exe (~8.5 MB); portable, per-user install, or /silent machine-wide
LicenseGPLv3; source zip attached to every release