Notepatra Documentation
A native C++/Rust code editor with local-first AI — six backends in the dropdown (Ollama, llama.cpp, Ollama Cloud, OpenRouter, OpenAI, Azure OpenAI), plus any OpenAI-compatible server (any OpenAI-compatible server) reachable via the llama.cpp entry. Fast, portable, free forever under GPL-3.0. This is the complete reference for installing, using, customizing, and extending Notepatra.
Introduction
Notepatra is a native code editor written in C++17 with a Rust core for the heavy-lifting (memory-mapped file I/O, Aho-Corasick search, Myers diff, formatters). It targets Linux x64 / ARM64, macOS Apple Silicon, and Windows x64. The bare executable is ~12 MB (12.2 MB on Linux x64) on each platform; downloads range 4.1 MB (Linux ARM64) to ~42.7 MB (Windows MSI with Qt DLLs bundled).
Unlike Electron-based editors, Notepatra does not ship a browser runtime. It uses Qt5 + QScintilla — a battle-tested Scintilla-based editor engine — so 238 file types, 82 language lexers, brace matching, folding, and code completion are built in.
Unlike cloud-first editors, Notepatra's AI is local-first. The AI dock dropdown ships six backends: Ollama (default · localhost:11434), llama.cpp's llama-server (loads any GGUF directly · localhost:8080), OpenRouter (cloud · 100+ models — Claude, GPT, Gemini, Grok, Kimi, …), Ollama Cloud (cloud · gpt-oss:120b, qwen3-coder:480b, deepseek-v3.1:671b), OpenAI direct, and Azure OpenAI (enterprise). The llama.cpp entry also accepts a user-configured base URL via Settings → Preferences → AI, so it can reach any OpenAI-compatible HTTP server you've installed. Nothing leaves your computer unless you pick a cloud backend. No mandatory API keys, no subscription, no telemetry.
The AI runs as an agent. Tick Coding Mode in the AI dock (with a workspace open and a tool-capable model) and the model gets up to 13 native tools — file tools read_file, list_dir, write_file, search, apply_diff; data tools query_sql, csv_query, generate_chart; and read-only git tools git_status, git_diff, git_log, git_branch_list, git_show — plus three-layer path safety, a 25-call hard cap per turn, and persistent per-workspace chat history. See Coding Mode (agentic) below for the full surface.
Install
Quick install (recommended)
Linux
curl -fsSL https://notepatra.org/install.sh | sh
Downloads the latest release for your architecture (x64 or ARM64), verifies SHA-256, installs to ~/.local/bin/notepatra, creates a .desktop entry, and registers the hicolor icon theme. Rerun to upgrade.
macOS (Apple Silicon only)
curl -fsSL https://notepatra.org/install.sh | sh
Same script. Downloads .dmg, mounts it, copies Notepatra.app to /Applications, unmounts. Intel Macs are not shipped pre-built — build from source.
Windows (PowerShell)
irm https://notepatra.org/install.ps1 | iex
Downloads the portable notepatra-windows-x64.zip, extracts it to %LOCALAPPDATA%\Notepatra, adds that directory to your user PATH, creates Start Menu + Desktop shortcuts, and writes its own uninstall entry (registered in Settings → Apps → Installed apps via an HKCU Uninstall key + bundled uninstall.ps1). No NSIS installer or notepatra-setup.exe is involved.
Manual download
Every release is at github.com/singhpratech/notepatra/releases/latest.
| Platform | Asset | Size |
|---|---|---|
| 🐧 Linux x64 | notepatra-linux-x64.tar.gz | ~4.4 MB |
| 🐧 Linux ARM64 | notepatra-linux-arm64.tar.gz | ~4.1 MB |
| 🍎 macOS Apple Silicon | notepatra-macos-arm64.dmg | ~27.7 MB |
| 🪟 Windows x64 (MSI) | notepatra-<version>.msi | ~42.7 MB |
| 🪟 Windows x64 (installer) | notepatra-setup-<version>.exe | ~32.8 MB |
| 🪟 Windows x64 (portable) | notepatra-windows-x64.zip | ~37.4 MB |
sudo apt install qtbase5-dev libqscintilla2-qt5-dev. On Fedora: sudo dnf install qt5-qtbase qscintilla-qt5. On Arch: sudo pacman -S qt5-base qscintilla-qt5. Mac/Windows downloads bundle Qt.
Uninstall
Notepatra installs cleanly and uninstalls cleanly. Pick your platform and the path you used to install. Every command below is copy-paste ready.
ollama CLI.
🍎 macOS (Sonoma · Sequoia · Tahoe)
One-liner
curl -fsSL https://notepatra.org/uninstall.sh | sh
Auto-detects macOS and removes the app, CLI symlink, and user data. Uses sudo if /Applications is not writable.
Manual (any install path)
# Remove the app (sudo only if /Applications is not writable)
sudo rm -rf /Applications/Notepatra.app
# …or if you installed to ~/Applications instead:
rm -rf ~/Applications/Notepatra.app
# Remove the CLI symlink
rm -f ~/.local/bin/notepatra
# Remove user config + cache + saved state
rm -rf ~/.config/notepatra
rm -rf ~/Library/Preferences/com.notepatra.editor.plist
rm -rf ~/Library/Saved\ Application\ State/com.notepatra.editor.savedState
rm -rf ~/Library/Caches/com.notepatra.editor
What Notepatra does NOT create
- No system-wide
LaunchAgents/LaunchDaemons - No Homebrew, MacPorts, or other package-manager entries
- No kernel extensions
- No background daemons
🐧 Linux (Ubuntu · Debian · Fedora · Arch · any distro)
One-liner
curl -fsSL https://notepatra.org/uninstall.sh | sh
Manual (install.sh path)
# Remove the binary
rm -f ~/.local/bin/notepatra
# Remove the desktop entry
rm -f ~/.local/share/applications/notepatra.desktop
# Remove icons (all sizes)
for sz in 16 32 48 64 128 256; do
rm -f ~/.local/share/icons/hicolor/${sz}x${sz}/apps/notepatra.png
done
gtk-update-icon-cache ~/.local/share/icons/hicolor 2>/dev/null
# Remove user config + cache + recovery
rm -rf ~/.config/notepatra
# Refresh the application menu so the launcher disappears
update-desktop-database ~/.local/share/applications 2>/dev/null
Manual (tarball extracted somewhere else)
# Find where you put it
which notepatra
# /opt/notepatra/notepatra ← example
# Remove that directory
sudo rm -rf /opt/notepatra
rm -f ~/.local/share/applications/notepatra.desktop
rm -rf ~/.config/notepatra
If you built from source
cd /path/to/notepatra-build
sudo cmake --build . --target uninstall # if you ran `make install`
# Or just delete the source tree:
cd .. && rm -rf notepatra
What is NOT touched
- System Qt5 and QScintilla packages — shared with other apps, never auto-removed
- Ollama — separate program, manage via the
ollamaCLI - Files you opened or edited with Notepatra
🪟 Windows 10 · 11
If you installed via the NSIS installer (notepatra-setup-X.Y.Z.exe)
Easiest: use Windows Settings.
- Open Settings (Win+I)
- Apps → Installed apps
- Search for Notepatra
- Three-dot menu → Uninstall
- The NSIS uninstaller runs → Next → Uninstall
Alternative: run the uninstaller directly from %LOCALAPPDATA%\Notepatra\uninstall.exe.
The uninstaller automatically removes:
%LOCALAPPDATA%\Notepatra\(the entire install directory + Qt DLLs)- Start Menu shortcut
- Desktop shortcut (if you opted in)
- PATH entry (if you opted in)
HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\Notepatra
One-liner (PowerShell)
irm https://notepatra.org/uninstall.ps1 | iex
Manual (PowerShell)
# Remove install directory (Qt DLLs + .exe + uninstall.ps1)
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\Notepatra"
# Remove Start Menu + Desktop shortcuts
Remove-Item -Force "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Notepatra.lnk"
Remove-Item -Force "$env:USERPROFILE\Desktop\Notepatra.lnk"
# Remove from user PATH
$p = [Environment]::GetEnvironmentVariable("PATH", "User") -split ';' |
Where-Object { $_ -notlike "*Notepatra*" } | Where-Object { $_ }
[Environment]::SetEnvironmentVariable("PATH", ($p -join ';'), "User")
# Remove the Installed Apps registry entry
Remove-Item -Recurse -Force "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\Notepatra"
# Remove user config + saved state
Remove-Item -Recurse -Force "$env:USERPROFILE\.config\notepatra"
Remove-Item -Recurse -Force "$env:APPDATA\Notepatra"
Portable zip
If you ran notepatra-windows-x64.zip, no installer was run — just delete the folder you extracted.
Remove-Item -Recurse -Force C:\path\to\notepatra-folder
What is NOT touched
- Visual C++ Redistributables (used by other apps)
- Files you opened or edited with Notepatra
- Ollama installation
First launch
Launch Notepatra from your start menu / Launchpad / notepatra command. You'll see an empty editor with the menu bar, toolbar, tab bar, status bar, and (collapsed) side panels.
The first time you run Notepatra, it creates its per-user config directory — ~/.config/notepatra/ on Linux, %APPDATA%\Notepatra\ (Roaming) on Windows, ~/Library/Application Support/Notepatra/ on macOS — and writes a default config.json. Themes, fonts, tab width, word wrap, etc. are persisted there.
Lite mode vs Full mode (v0.1.64+)
Starting in v0.1.64, Notepatra ships two build flavors per release. Lite is the default download — a bare ~12.2 MB binary with no heavy dependencies bundled. Full is the opt-in flavor. On every platform it bundles the DuckDB query engine (v1.1.3) next to the binary; on Linux and Windows it additionally bundles QtWebEngine for inline Vega-Lite chart rendering. macOS Full is DuckDB-only — Homebrew's qt@5 no longer ships QtWebEngine (and there is no Apple-Silicon Qt5 WebEngine), so inline Vega charts stay a Linux/Windows Full feature; the native fenced ```chart renderer (QtCharts) still works everywhere. On Linux the -full tarball links libQt5WebEngineWidgets from your distro (install qtwebengine5-dev / qt5-qtwebengine) and ships libduckdb.so alongside the binary. Heavy features go through packs that you install on demand, the way DuckDB ships a tiny core plus optional extensions (httpfs, parquet, spatial, etc.).
Why this split?
v0.1.63 bundled QtWebEngine into every release for one specific feature — the AI Data Analyst's inline chart card. Most users will never trigger a chart, but every install paid the disk + download cost. v0.1.64 flipped the default: lite by default, charts move to an optional pack. Same architecture mirrors how Cursor / VS Code / Sublime add language servers and renderers — small core, install what you need.
| Flavor | Bare binary | What you get | What's missing |
|---|---|---|---|
| Lite (default) | ~12 MB | Everything: editor, lexers, AI Assistant, Coding Mode, Data Analyst tool calls, Git, REST client, hex editor, plugins, themes. | Inline Vega-Lite chart rendering. The Data Analyst can still generate chart specs — they show as a "Chart rendering requires the Charts Pack" card with [View JSON instead] to copy the spec out. |
| Full (opt-in) | Larger than Lite — see release page | Everything in Lite, plus the bundled DuckDB engine (every platform) and the QtWebEngine-backed renderer that paints Vega-Lite specs inline in the chat transcript (Linux/Windows; macOS Full is DuckDB-only — see note below). | — |
Packs — what's installed where
The plugin loader (src/plugin_loader.{h,cpp}) tracks which packs are available. Each pack lives under your per-user plugin directory:
- Linux:
~/.local/share/notepatra/plugins/<pack>/ - macOS:
~/Library/Application Support/notepatra/plugins/<pack>/ - Windows:
%APPDATA%/notepatra/plugins/<pack>/
As of v0.1.114, the Full flavor ships the charts pack bundled on Linux and Windows (it's the same binary — the pack is "installed" if WebEngine was linked at compile time; macOS Full is DuckDB-only and has no inline Vega renderer). The in-app download / SHA-256 verification / runtime QPluginLoader activation path is scaffolded but not yet wired (still queued as of v0.1.114), so today packs are added by swapping in the Full binary rather than downloaded inside the app.
| Pack ID | Size | What it does | Status |
|---|---|---|---|
charts |
In Full binary | Renders Vega-Lite charts (bar / line / scatter / area / composite) inline in the chat transcript. Powered by QtWebEngine + vega-embed — Linux & Windows Full only. | Bundled in the Full flavor on Linux x64 / Linux ARM64 (tar.gz) and Windows (MSI / zip). The macOS DMG does not include it — macOS Full is DuckDB-only (Homebrew qt@5 dropped QtWebEngine). All platforms have explicit Lite (default) and Full downloads; Full bundles DuckDB everywhere, plus the WebEngine inline Vega-Lite renderer on Linux/Windows. |
pdf |
≈ 12 MB | Rasterises PDFs to PNG pages so vision-capable AI models can read them. Powered by Poppler-Qt5. | Still queued (not shipped as of v0.1.114). Until then, dragging a PDF into the AI dock shows the "use a vision-capable model" error bubble. |
Upgrading from Lite to Full
Three paths, pick whichever matches your situation:
Path A — Click [Install charts pack] in the app
When you ask the AI Assistant to chart something in Data Analyst mode, the lite binary shows a Chart rendering requires the Charts Pack card with two buttons:
- [Install charts pack] — opens a dialog explaining the lite/full split, then opens your default browser to the GitHub Releases page for the current tag. On Linux/Windows pick the file ending in
-fullfor your OS. On macOS the-fullDMG adds the DuckDB engine only — inline Vega-Lite charts remain unavailable (no Apple-Silicon Qt5 WebEngine); use [View JSON instead] or a native```chartblock, which renders on every platform. - [View JSON instead] — appends the raw Vega-Lite spec under the card as a fenced code block. You can copy it into any standalone Vega-Lite editor (vega.github.io/editor) without installing anything.
Path B — Download the Full flavor manually
On the GitHub Releases page pick the file with -full in the name:
- Linux x64:
notepatra-linux-x64-full.tar.gz— extract it, then replace~/.local/bin/notepatra(or wherever you installed). Your config, chat history, and connections live outside the binary and are preserved. - Linux ARM64:
notepatra-linux-arm64-full.tar.gz— same pattern. - macOS:
Notepatra-full.dmg— the Full flavor with the DuckDB engine bundled. (macOS Full is DuckDB-only; inline Vega-Lite charts need QtWebEngine, which Homebrewqt@5no longer ships.) Drag to Applications as usual; your config, chat history, and connections are preserved. - Windows:
notepatra-full-*.msiornotepatra-windows-x64-full.zip— MSI installs the Full flavor; zip is the portable equivalent. Your config, chat history, and connections are preserved.
Path C — Build from source with -DNOTEPATRA_WITH_WEBENGINE=ON
Works on any platform with QtWebEngine dev headers available:
- Linux:
sudo apt-get install qtwebengine5-dev libqt5webenginewidgets5(Debian / Ubuntu) orsudo dnf install qt5-qtwebengine-devel(Fedora) orsudo pacman -S qt5-webengine(Arch) - macOS: Homebrew
qt@5no longer bundles QtWebEngine (Chromium CVEs), and there is no Apple-Silicon Qt5 WebEngine — so the inline Vega-Lite renderer isn't available on macOS. The prebuilt macOS Full gives you the DuckDB engine; build with-DNOTEPATRA_FULL=ON - Windows: The install-qt-action equivalent (or aqtinstall)
qtwebenginemodule
Then:
git clone https://github.com/singhpratech/notepatra.git
cd notepatra
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DNOTEPATRA_WITH_WEBENGINE=ON
make -j$(nproc)
./notepatra
The binary will report a normal version string but the chart renderer's WebEngine code path is now compiled in, so the Data Analyst's chart cards render inline instead of showing the install prompt.
FAQ
- Do I lose anything by staying on Lite? No — every editor / lexer / AI / Git / data / plugin feature works identically. The only difference is that
generate_charttool results paint as a "Chart rendering requires the Charts Pack" card instead of as an inline rendered chart. You can still see the spec via [View JSON instead] and copy it elsewhere. - Can I downgrade Full → Lite? Yes. Just download the Lite tarball and replace the binary. Your config / chat history / connections are preserved (they live under
~/.config/notepatra, not inside the binary). - Will the chart spec data be lost if I'm on Lite? No — the AI's tool result is preserved in your chat history just like any other tool result. If you upgrade to Full later, opening the same chat shows the rendered chart for those past results.
- When does the in-app installer ship? Still queued as of v0.1.114. The architectural pieces (plugin_loader, manifest schema, download path) are scaffolded in v0.1.66; what's left is the actual HTTP fetch + SHA-256 verify +
QPluginLoader::loadwiring, plus testing across macOS / Windows runners.
UI overview
- Menu bar — File, Edit, Search, View, Tools, Encoding, Language, Settings, Utilities, Plugins, Macro, Run, Window, Help. Most actions have keyboard shortcuts (full list).
- Toolbar — the Built-in Tools bar with tool-launch buttons: Project Search, AI, Terminal, Compare, JSON, HTML, SQL, Brackets, REST, Noter, Diagram.
- Tab bar — one tab per open file. Modified tabs show a dot. Close with the
×or middle-click. - Editor area — Scintilla-based editor with line numbers, code folding, brace matching, syntax highlighting, caret-line highlight, word-wrap toggle, EOL visibility toggle, rulers, optional crosshair.
- Status bar — language, file length, line count, word count, cursor line/col, EOL type (CRLF/LF), encoding, INS/OVR.
- Side panels — File Explorer, Function List, Search Results, AI Assistant. Dockable/floatable.
Editor basics
The editor is QScintilla 2.14.1 (official Riverbank source) under the hood: folding, brace matching, auto-indent, bookmarks, multi-cursor (Ctrl+click), rectangular/column selection (Alt+drag), and word-based code completion are all built in.
Opening & saving
- New Ctrl+N — empty untitled tab
- Open Ctrl+O — multi-select file dialog, opens each as a tab
- Save Ctrl+S — save current tab (prompts for path if untitled)
- Save As Ctrl+Shift+S (also right-click tab → Save As, or File menu) — opens the platform Save dialog with a ~72-entry file-type dropdown covering every supported language (Plain Text, Markdown, Python, JavaScript, TypeScript, C/C++, Rust, Go, SQL, JSON, YAML, TOML, HTML/CSS, Bash, Dockerfile, …). The filter matching the current tab's language is pre-selected, matching Notepad++ behaviour. Filter helper lives in
src/lexerutils.cpp::buildSaveAsFilters(). Added v0.1.88 — pre-fix the dropdown only ever offered "All Files (*)". - Save All Ctrl+Alt+S — saves every modified tab with a known path
- Close Ctrl+W — close current tab (prompts to save if modified)
- Drag & drop files from the OS file manager into the editor — they open as tabs
File-size limits
Notepatra uses the Rust core's memory-mapped file loading to avoid a double read on open; the file is then held in the editor buffer (peaks at roughly 3x file size in RAM during load (~1-2x once loaded)). Limits:
- Up to 50 MB — full syntax highlighting, auto-completion, word wrap, indent guides, all features enabled
- 50 MB – ~1.86 GB (v0.1.88 hardened) — syntax highlighting, auto-completion, word wrap, indent guides, and edge column all disabled for performance; still fully editable. Find → Mark All caps the indicator fills at 10,000 highlights to keep paint cycles bounded.
- Above ~1.86 GB — the file opens truncated and read-only; use a streaming tool like
lessfor the full content.
Load-path optimisations (v0.1.88). Opening a 118 MB UTF-8 file used to take ~1.5 s and peak ~700 MB RAM; v0.1.88 brings it to ~600 ms and ~360 MB. Three fixes in rust-core/src/file_io.rs: a UTF-8 fast path validates with std::str::from_utf8 (SIMD-accelerated) and skips the UTF_8.decode() allocation entirely when the mmap bytes are already valid UTF-8; EOL detection is bounded to the first 64 KB instead of two full-text scans; and the Rust→C FFI handoff now delivers a length-prefixed Box<[u8]> through a new npc_free_file_text(ptr, len) entry-point instead of the old NUL-terminated CString round-trip — saves ~118 MB of heap on a 118 MB file. UTF-16 / UTF-32 / Windows-1252 paths unchanged.
Languages & lexers
Notepatra ships 82 language lexers as of v0.1.114 (covering 238 file extensions). The Language menu is split into a narrow two-tier layout — Common + SQL Dialects at the top, More Languages as an alphabetical submenu of the rest. Extensions are auto-detected from the filename.
Core (Qt-bundled): Python, JavaScript/TypeScript/JSX, CoffeeScript, C/C++, C#, D, Java/Kotlin, HTML/PHP, CSS/SCSS/LESS, XML, JSON, SQL (ANSI / T-SQL / PL/SQL / MySQL / PostgreSQL / SQLite), Bash, Batch, Ruby, Perl, Lua, TCL, Fortran, Matlab, Octave, IDL, NASM, MASM, Verilog, VHDL, TeX, PostScript, POV, Spice, AVS, Properties, PO, IntelHex, SRecord, Markdown, YAML, Diff, Pascal, CMake, Makefile.
v0.1.55 additions (32 dedicated lexers, keyword tables verified against official specs): Dart · Solidity · Zig · Vala · Hack · Julia · R · Protobuf · F# · HCL/Terraform · Thrift · GraphQL · GDScript · Nim · Cython · Mojo · Crystal · Elixir · Scala · Groovy · Apex · Jinja · Liquid · Twig · Dockerfile · Fish · Nushell · TOML · DotEnv · Gitignore · JSON5 · BibTeX. Each ships with comment / uncomment / block-comment syntax (Ctrl+/ for line, Ctrl+Shift+Q for block) and proper file-extension routing — .dart, .zig, .jl, .toml, .ex, Cargo.toml, Dockerfile, .gitignore, .env, .fish, .json5, .tf, etc. now point at their dedicated lexers instead of falling back to the closest-fit generic.
Themes & palette
Three themes ship: Light (default), Dark, and Monokai. Change via Settings → Theme. The theme is persisted in config.json.
Every theme applies a curated 9-hue palette: keywords blue bold (#0000FF), types violet (#8000FF), comments green italic (#008000), numbers orange (#FF8000), strings grey (#808080), operators navy bold (#000080), preprocessor brown (#804000), classes maroon (#7F0000), identifiers plain (default text). Dark theme uses Zenburn-derived hues (warm sand keywords, sage types, rose strings, olive operators, peach preprocessor) so each token kind is on a distinct hue arc — no more "all blue shades" effect. The palette is driven by lexer->description(i) — it walks every style slot in every lexer, matches substrings like "keyword", "comment", "string", and paints accordingly. Works across all 82 lexers without hard-coding.
Rulers & crosshair overlay
Optional visual aids for long files and precise cursor placement:
- Document rulers — thin horizontal + vertical ruler bands showing pixel offsets from the top-left corner. Toggle:
View → Document Rulers. - Crosshair overlay — a thin line extending from the caret position to both edges of the editor, making the current line + column unmistakable. Toggle:
View → Crosshair.
Find & replace
5-tab dialog: Find, Replace, Find in Files, Mark, Go to.
- Normal / Extended / Regex modes — extended supports
\n,\t,\xNNescapes; in-document Find/Replace uses Scintilla's built-in regex; recursive Find in Files counts matches via a Rust regex engine. - Match case, Whole word, Wrap around, In selection checkboxes.
- Find in Files walks a directory recursively (respects glob patterns), results land in the Search Results panel — double-click to jump to line.
- Mark highlights every occurrence of a pattern without moving the caret. On files larger than 50 MB the indicator fill is capped at 10,000 highlights (v0.1.88) so the redraw doesn't stall the UI — the result label reports e.g. "Marked first 10000 of 124312 occurrence(s) — capped for performance on large files".
- Find / Replace All across all open tabs — one click.
Project Search (Ctrl+Shift+G)
A separate, full-tab search dedicated to scanning an entire folder tree. Designed for the "where is this used across the whole project?" workflow — different from the inline Find & Replace dialog (which targets the current document or open tabs). Streams results live as files are scanned; safe on multi-GB log files.
What it searches
- File contents — every line of every text file under the selected folder. Skips binary files automatically (NUL-byte heuristic in the first 4 KB).
- File names — when Also match file names is ticked, files whose basename matches the query show up at the top of the results, separately from content matches.
- Heavy directory pruning —
.git,node_modules,build,target,dist,.venv,venv,__pycache__,.cache,.gradle,DerivedData,.idea,.vsare skipped at the directory level so a 10k-filenode_modulesdoesn't drown your results. - OneDrive / cloud-placeholder skip on Windows — files marked offline by cloud-storage providers are skipped (would otherwise hang the search waiting for a download).
Query modes
- Plain text (default) — substring match. Multi-word phrases work directly: search
import os(with the space) and you get every file that contains that exact phrase. No quoting needed. Internal whitespace is preserved; leading/trailing whitespace is auto-trimmed (so" import os "matches the same lines as"import os"). - Match case — toggle case-sensitive matching.
- Whole word — wraps the query in
\b...\bword boundaries. For multi-word phrases the boundaries land at the start/end of the phrase, soimport oswith whole-word ON matchesimport osbut notmyimport os.path. - Regex — Rust regex syntax (no PCRE backreferences). Powers patterns like
\bfn\s+\w+for "all Rust function definitions." - Also match file names — adds filename hits to the result list.
- Include binary files — off by default. Tick to also scan binaries (rare; useful for hex strings).
Engine
Plain-text searches under ~50 MB per file route through a Rust Aho-Corasick fast path (multiple patterns at once, sub-millisecond on small files). Larger files and regex queries use a streaming line-by-line scanner. Each match reports line:column (column is 1-based and counted in characters, not bytes — UTF-8 multi-byte sequences count as one).
Results
Results stream into a tree-grouped panel: one node per file with hits, expandable to per-line snippets. Double-click any hit to jump the editor to the exact line and column. Live counters show files scanned, matches so far, and elapsed time. Cancel the search any time — the worker thread bails on the next file boundary.
Macros
Record keyboard + mouse operations and play them back:
- Ctrl+Shift+M — start recording
- Ctrl+Shift+T — stop recording
- Ctrl+Shift+P — Playback (play last macro)
Macro → Run Multiple Times...— play N timesMacro → Save Current Macro...— write the macro to a user-chosen.macrofile (QsciMacro serialization, not JSON; no fixed directory)Macro → Load Macro...— restore a saved.macrofile
Uses QScintilla's built-in QsciMacro serialization.
Sessions & crash recovery
On close, Notepatra saves session.json in its per-user config directory (~/.config/notepatra/ on Linux; %APPDATA%\Notepatra\ on Windows; ~/Library/Application Support/Notepatra/ on macOS): list of open file paths, cursor positions, window geometry, maximized state, theme, active tab. On next launch, all tabs reopen at the same cursor positions.
Roughly every 5 seconds (configurable 1–300 s) Notepatra writes full unsaved-buffer content into session.json — that file is the recovery store. If the app crashes (caught by SIGSEGV/SIGABRT/SIGFPE handlers), a .crash_flag is left in the config directory's recovery/ folder and the next launch detects it and offers to restore unsaved work.
JSON Tools (inbuilt)
Open: Tools → JSON Tools (inbuilt). Panel opens as a new tab.
Buttons
- Format — parses JSON, pretty-prints with 4-space indent via Rust's
serde_json. Falls through to a manual pretty printer for broken JSON. - Minify — strips all whitespace. Attempts to fix first, then minifies; if unparseable, strips whitespace with
replace(whitespace, ""). - Fix + Format — runs the deterministic Rust fixer (
RustCore::fixJson) which handles: single→double quote conversion, unquoted keys, missing closing braces/brackets (stack-based), trailing comma removal, nested-brace insertion via regex passes. Produces a human-readable report like"Fixed 2 issue(s): Added 3 missing closer(s) at end: ]}}; Removed 1 trailing comma(s)". - AI Fix (Ollama) — sends the broken JSON to your local Ollama model with a strict minimal-change prompt. See AI Fix pipeline for details.
- Show Diff — opens a side-by-side Compare tab with the original on the left and the last fix's output on the right. Works for any action: Format, Minify, Fix+Format, AI Fix.
- Copy Output — copies the current panel content to the clipboard.
Session log
Below the Scintilla output, a small list widget records every action taken during the session with before/after char counts, a delta, and a smart description:
[14:22:31] Format: 60 → 86 chars (+26) +2 commas, +1 brace
[14:22:45] AI Fix (Ollama): 60 → 63 chars (+3) +2 commas [5 lines]
[14:23:02] Minify: 98 → 60 chars (-38)
Color-coded: teal for "added/fixed", amber for "shrunk/minified", gray for no-op. Capped at 50 entries, scrollable.
HTML Tools (inbuilt)
Same structure as JSON Tools but with HTML-specific buttons: Format (2 spaces), Format (4 spaces), Minify, Fix + Format, AI Fix, Show Diff, Copy Output. Fixer handles: self-closing <img>/<br>, mismatched tags, attribute quotes.
Bracket Tools (inbuilt)
Generic bracket/quote balancer. Works on any language. Uses the Rust core's bracket_fix module which walks the input, tracks a bracket stack, and closes any unclosed opens at the end in reverse order.
SQL Formatter (inbuilt)
Open: Tools → SQL Formatter (inbuilt).
- Dialect dropdown — ANSI SQL / T-SQL (SQL Server) / PL/SQL (Oracle) / MySQL / PostgreSQL / SQLite. Switching dialect re-colorizes the visible buffer with that dialect's keywords.
- UPPERCASE keywords checkbox — toggles keyword casing in the formatted output.
- Indent spin box — 1–8 spaces.
- Format button — invokes the Rust SQL formatter.
Dialect-specific keyword sets are fed to Scintilla via SCI_SETKEYWORDS (since QsciLexerSQL::setKeywords is protected). T-SQL adds DECLARE/MERGE/OUTPUT/PIVOT/OVER/PARTITION, PL/SQL adds PLS_INTEGER/SYSDATE/NVL/DECODE/CONNECT BY, etc.
Compare
A side-by-side diff view; open via Tools → Compare (inbuilt). Backed by Rust's Myers diff (similar crate) and a custom CompareWidget rendered with Qt.
Visual UX inspired by ComparePlus by Pavel Nedev. Notepatra's implementation is a fresh Qt + Rust port in a different codebase, but the visual conventions are credit to Pavel.
How it works
- Pick a left and right file (open tab, unsaved tab, or file on disk).
- Rust's Myers diff (
similarcrate) produces a list of Equal / Insert / Delete entries. - Consecutive Delete + Add blocks are paired into "modified" rows at the same visual line.
- Within paired modified rows, a common-prefix + common-suffix detector finds the exact differing bytes and highlights only those characters — not the whole line.
Visual markers
| Row kind | Background | Symbol margin | Character highlight |
|---|---|---|---|
| Equal / context | white | — | — |
| Modified (paired) | pale yellow #FFFBE6 | pink ~ (Circle) | red box on left, green box on right — only differing chars |
| Added (right only) | mint green #D4F4D4 | green + (Plus) | — |
| Deleted (left only) | salmon #F4D4D4 | red − (Minus) | — |
| Placeholder (empty on one side) | light blue #E8F0F8 | green + in margin | — |
Line numbers
Each panel uses a TextMargin with custom per-row text. The LEFT panel shows the original LEFT-source line numbers; the RIGHT panel shows the original RIGHT-source line numbers. They diverge cleanly when there are insertions/deletions — the empty placeholder on one side shows a green + instead of a number.
Toolbar
- < Prev / Next > — jump to previous/next diff
- Recompare — re-run the diff algorithm
- Ignore spaces — defaults to ON as of v0.1.36. Whitespace-only differences (re-indentation, alignment, trailing spaces) are collapsed so they don't show up as diffs. Untick for byte-exact mode (useful for YAML / Python where indentation IS the meaning).
- Ignore case, Ignore empty lines — toggle and recompute
Scroll sync
Both vertical and horizontal scrollbars are mirrored. Drag either side's scrollbar and both panels move together. Qt's built-in valueChanged signal is naturally cycle-safe because setValue(x) is a no-op when x == current.
Git integration
Opens as a dockable panel. Shows:
- Current branch name with upstream tracking status
- Changed files list — added (green), modified (yellow), deleted (red), untracked
- Git gutter in the editor margin — colored line markers for added/modified/deleted lines compared to HEAD
- Commit / Push / Pull / Fetch buttons
Shells out to git via QProcess. Non-invasive — no libgit2 dependency.
Terminal
Built-in terminal panel (Linux/macOS/Windows). Uses QProcess to spawn the platform shell (bash/zsh on Linux/macOS, pwsh→cmd.exe on Windows) and feeds stdout/stderr to a monospace widget, rendering ANSI colour escapes. Not a full pty (no curses) — fine for simple commands and scripts, not for vim/htop.
REST client
A Postman-lite panel: URL field, method dropdown (GET/POST/PUT/PATCH/DELETE/HEAD/OPTIONS), headers editor, monospace request body editor, response viewer with pretty-printed JSON output + status code + timing.
Hex editor
Byte-level view of any file. Left column: offset. Middle: hex bytes in 16-byte rows. Right: printable ASCII. Read-only for now.
AI integration overview
Notepatra's AI is local-first by default with optional cloud backends. As of v0.1.55, six backends are available — pick from the AI dock dropdown:
| Backend | Type | Protocol / URL | What it gives you |
|---|---|---|---|
| Ollama (default) | Local | Native /api/generate · http://localhost:11434 | Easiest to install. One-line install, auto-detects models with /api/tags. /api/show capability probe (v0.1.55) auto-detects which models support tools / thinking / vision. |
| Ollama Cloud | Cloud | OpenAI-compat over HTTPS · https://ollama.com | Same Ollama models, served from Ollama's hosted infrastructure. Per-provider key slot in Settings. |
| llama.cpp | Local | OpenAI /v1/chat/completions · http://localhost:8080 | Loads any GGUF file directly — no daemon, no config format. Maximum control + minimum overhead. |
| OpenRouter | Cloud | OpenAI-compat · https://openrouter.ai/api | One key, hundreds of models (Anthropic, OpenAI, Google, Mistral, Meta, xAI, DeepSeek, Qwen). Unified reasoning field — Think checkbox toggles thinking on Claude / o-series / Gemini consistently. |
| OpenAI | Cloud | OpenAI /v1/chat/completions · https://api.openai.com | Direct OpenAI access for the GPT-4o / GPT-5 / o-series families. Per-provider key slot. |
| Azure OpenAI | Cloud | Azure deployment URL with ?api-version=... | Enterprise OpenAI through your Azure subscription. Configure resource name + deployment name + API version in the dedicated Azure section of the Settings dialog. |
If the selected backend isn't reachable, AI panels show a backend-specific banner (e.g. "Ollama not running — start it: ollama serve", or for cloud backends "OpenRouter key not set — open Settings"). The cloud-config banner is red when keys are missing for the selected backend, green when configured.
Per-provider key slots (v0.1.55). The AI Settings dialog has a 4-section layout — OpenRouter, OpenAI, Ollama Cloud, Azure OpenAI — each with its own Test / Save / Forget buttons and key slot. Strict no-cross-provider lookup: the OpenRouter backend will never accidentally use the OpenAI key, and vice-versa. Legacy single-key configs migrate automatically by sniffing the prefix (sk-or- → OpenRouter, sk- → OpenAI).
Searchable model dropdown (v0.1.55). Type any provider key (openai, anthropic, google, xai) or alias (grok, claude, gpt, gemini, kimi, qwen) and the dropdown filters to that provider's models — works whether you remember the brand name or the model name.
AI surfaces in Notepatra:
- AI Fix buttons in the JSON Tools / HTML Tools / Bracket Tools inbuilt tools — sends broken content, gets fixed content back
- AI Assistant panel — general-purpose chat with your code, supports multi-turn, attach files, voice input. Modes: Chat / Coding / Data Analyst.
- Status bar in every AI panel showing connectivity dot, the searchable model dropdown, and a refresh button
Privacy: "Auto-attach open file" toggle (v0.1.55). The Auto-attach open file checkbox (it reads "Auto-attaching open file" while on, styled red-when-off / green-when-on like a lock indicator) controls whether the file currently in the editor is included in the AI's context. Default OFF. Available only in Coding Mode — Chat and Data Analyst modes never see file content. The system prompt teaches the model to politely instruct you to enable the toggle if asked "can you see this file?".
Credential scrubber (v0.1.55). Every editor-derived chunk (selection, workspace block, attached file, user input) passes through a 20+-pattern redactor before leaving the machine — OpenRouter / Anthropic / OpenAI / GitHub / GitLab / AWS / Slack / Stripe / SendGrid / Google API / JWT / PEM private-key blocks / generic password=/api_key=/token=. Replacement is in-place with a [REDACTED-VENDOR-KEY] marker so the model still sees that a credential was redacted.
Ollama setup
- Install Ollama —
curl -fsSL https://ollama.com/install.sh | sh(Linux/macOS) or download from ollama.com (Windows). - Start the daemon —
ollama serve. Listens onhttp://localhost:11434by default. - Pull at least one model. Recommended starter:
ollama pull qwen2.5:7b— 4.7 GB, general-purpose, good at codeollama pull llama3.2:3b— 2 GB, smaller, fasterollama pull codellama:7b— 3.8 GB, code-specializedollama pull qwen2.5-coder:7b— 4.4 GB, code-specialized + recent
- Launch Notepatra → open any AI panel → the model dropdown auto-populates with whatever you pulled.
qwen2.5-coder:3b → qwen2.5:3b → gemma2:2b → gemma3:4b → llama3.2:3b.
llama.cpp setup (GGUF)
llama.cpp runs any .gguf file directly — no daemon, no config format. Best if you have specific GGUF models from Hugging Face and want maximum control.
- Install llama.cpp —
brew install llama.cpp(macOS) or build from the repo (Linux / Windows). - Download a GGUF model from huggingface.co. Try
Qwen2.5-Coder-3B-Instruct-Q4_K_M.gguf(~2 GB, excellent for code). - Run the server —
llama-server -m path/to/model.gguf --port 8080. Exposes OpenAI-compatible endpoints athttp://localhost:8080/v1/. - In Notepatra → Settings → Preferences → AI → pick "llama.cpp" → Save. Done.
AI backend setup — full guide
The condensed setup blocks above cover the happy path. This guide walks every supported backend through install, first-run, and the most common failure modes — per OS where the steps differ. Use it when something doesn't work or you're setting up a new machine.
Ollama (recommended for beginners)
One installer, auto-discovery of models, native HTTP API on port 11434. Works on every desktop OS Notepatra runs on.
🐧 Linux
- Install — one-liner provided by Ollama:
The installer drops a binary incurl -fsSL https://ollama.com/install.sh | sh/usr/local/bin/ollamaand registers a systemd unitollama.service. - Daemon — the installer starts and enables it. Check status:
If your distro has no systemd (Void, Artix, Alpine, WSL1), runsystemctl status ollama journalctl -u ollama -f # follow logsollama servein a terminal you keep open. - Pull a model:
ollama pull qwen2.5-coder:7b - Verify:
ollama list # should show the model curl http://localhost:11434/api/tags # JSON list of installed models - Notepatra config — open the AI dock, pick "Ollama" in the backend dropdown. The model dropdown auto-populates. No URL field to set;
http://localhost:11434is hard-wired.
🪟 Windows
- Install — download
OllamaSetup.exefrom ollama.com/download/windows and run it. Installs to%LOCALAPPDATA%\Programs\Ollamaand starts a tray icon at boot. - Daemon — the tray icon means it's running. Right-click the tray icon → "Quit Ollama" to stop. Re-launch from the Start menu.
- Pull a model — open PowerShell or cmd:
ollama pull qwen2.5-coder:7b - Verify:
ollama list curl http://localhost:11434/api/tags - Notepatra config — same as Linux: pick "Ollama" in the backend dropdown.
🍎 macOS
- Install — either the
.dmgfrom ollama.com/download/mac, or via Homebrew:brew install --cask ollama - Daemon — launching the Ollama app puts an icon in the menu bar and starts the server. Quit from the menu-bar icon to stop.
- Pull a model — open Terminal:
ollama pull qwen2.5-coder:7b - Verify:
ollama list curl http://localhost:11434/api/tags - Notepatra config — pick "Ollama" in the backend dropdown.
Troubleshooting
"Ollama not running" banner won't go away
Notepatra polls http://localhost:11434 and the banner stays red while the probe fails. Causes:
- Daemon not started —
systemctl start ollama(Linux) / launch the app (Win/macOS) /ollama serve(manual). - Wrong port — Ollama only binds
11434. If you setOLLAMA_HOST=0.0.0.0:11500or similar, Notepatra won't find it. Either unset that env var or restart Ollama on the default port. - Firewall — uncommon on localhost, but Windows Defender has been known to block first-time loopback connections. Allow
ollama.exewhen prompted. - Refresh — click the refresh button in the AI panel status bar to re-probe immediately instead of waiting for the next poll cycle.
Models don't appear in Notepatra dropdown
Ollama is reachable (banner is green) but the dropdown is empty or stale.
- Nothing pulled — run
ollama list. If empty, pull at least one model. - Pulled after Notepatra started — click the refresh button next to the model dropdown. Notepatra re-fetches
/api/tags. - Search filter active — the dropdown is searchable (v0.1.55). Clear the search text or type a fragment of the model name.
Model pulled but capability probe says no tools
v0.1.55 introduced an /api/show capability probe — Coding Mode hides models that can't call tools. If a model you expect to support tools is greyed out:
- Base / instruct distinction — only instruct-tuned models declare tool support.
qwen2.5:7bworks;qwen2.5-base:7bdoes not. - Old quant — re-pull the latest tag:
ollama pull qwen2.5-coder:7boverwrites the local copy with the current manifest, which may now include the tools capability flag. - Workaround — switch to Chat mode, which doesn't require tools, or pick a model from the curated list (Notepatra ships a known-good list per backend).
Out of memory on 7B+ models
Symptom: Ollama logs show llama_model_load: error loading model: failed to allocate buffer, or the daemon segfaults mid-generation.
- RAM budget — 7B Q4 needs ~6 GB free; 13B ~10 GB; 34B ~24 GB. Close browsers / VMs first.
- Pick a smaller quant —
ollama pull qwen2.5-coder:7b-instruct-q4_0uses ~1 GB less than the default Q4_K_M. - Drop to a 3B —
llama3.2:3b,qwen2.5-coder:3b, orgemma2:2ball run on 8 GB laptops. Notepatra auto-prefers these on memory-constrained machines. - GPU offload — set
OLLAMA_NUM_GPU=999to push all layers to VRAM if you have a discrete GPU.
llama.cpp (power users)
Maximum control. You pick the GGUF, you pick the quant, you pick the GPU layers. No daemon, no model registry — just llama-server with your file. Default port 8080, OpenAI-compatible at /v1.
🐧 Linux — build from source
- Clone and build:
Binaries land ingit clone https://github.com/ggml-org/llama.cpp cd llama.cpp cmake -B build -DGGML_CUDA=ON # or -DGGML_VULKAN=ON, or omit for CPU-only cmake --build build --config Release -jbuild/bin/. Add to PATH or copyllama-serversomewhere in your$PATH. - Verify:
llama-server --version
🪟 Windows — Releases zip
- Download the latest pre-built zip from github.com/ggml-org/llama.cpp/releases. Pick
llama-bXXXX-bin-win-cuda-x64.zipif you have an NVIDIA GPU, or...-vulkan-...for AMD/Intel, or...-avx2-...for CPU-only. - Extract to a folder you'll remember (e.g.
C:\llama.cpp) and add it to yourPATHenvironment variable, or always invoke with the full path. - Verify in PowerShell:
llama-server.exe --version
🍎 macOS — Homebrew
- Install:
Apple Silicon Macs get Metal acceleration by default — no extra flags needed.brew install llama.cpp - Verify:
llama-server --version
Picking a GGUF
GGUF is a quantised single-file model format. Smaller files run faster but lose accuracy. The sweet spot for 7B-13B models is Q4_K_M; pick higher only if you have spare VRAM.
| Quant | Size (7B) | Quality | When to pick |
|---|---|---|---|
Q4_K_M | ~4.4 GB | Good | Default. Fits on 8 GB RAM / 6 GB VRAM. Recommended. |
Q5_K_M | ~5.1 GB | Better | Noticeably sharper on coding. Needs ~10 GB free. |
Q8_0 | ~7.7 GB | Near-lossless | If you have 16 GB+ and want max fidelity short of full precision. |
F16 / BF16 | ~14 GB | Lossless | Research / fine-tuning. Overkill for chat. |
For ready-to-use quants, bartowski on Hugging Face publishes consistent re-quants of every popular release with all sizes side by side.
Running llama-server
Minimum command — just point at the GGUF:
llama-server -m /path/to/Qwen2.5-Coder-7B-Instruct-Q4_K_M.gguf --port 8080
Useful flags:
-c 8192— context window in tokens. Bigger = more RAM. Default 4096.-ngl 999— offload all layers to GPU (requires CUDA / Vulkan / Metal build).--host 0.0.0.0— bind to all interfaces. Default127.0.0.1(localhost only) is what Notepatra expects.--api-key SECRET— require an Authorization header. Leave off for local-only use.--jinja— use the model's chat template. Required for tool calls in Coding Mode.
In Notepatra, pick "llama.cpp" in the backend dropdown. The connectivity dot turns green and the model name (read from the running server) appears in the dropdown.
Troubleshooting
"llama-server not running" — but it IS running
Connectivity probe to http://localhost:8080/v1/models failed. Causes:
- Wrong port — Notepatra expects
8080. If you started--port 8000, restart with--port 8080. - Bound to a non-localhost interface — if you used
--host 192.168.x.x, Notepatra won't probe that. Use--host 127.0.0.1(default) or0.0.0.0. - Server still loading the model — large GGUFs take 30-60 s to mmap on first start. Watch the terminal until you see
HTTP server listening, then click refresh in Notepatra. - API key set on the server but not in Notepatra — if you started with
--api-key, paste the same key in Settings → AI → OpenAI-compat. Most users skip--api-keyentirely.
Curated catalog showing instead of my loaded model
The dropdown lists Notepatra's curated catalog rather than the model you loaded.
- Probe didn't reach
/v1/models— see "not running" above. The catalog is a fallback when the live probe fails. - Server returns an empty model list — older llama.cpp builds didn't return a name. Update llama.cpp; recent builds always populate
id. - You can still type any name — the dropdown is editable. Type the exact model id
llama-serverreports in its startup banner.
Cloud backends (OpenAI, OpenRouter, Azure, Ollama Cloud)
Cloud backends need a key. Notepatra has per-provider key slots — keys never cross-pollinate between providers. Open Settings → Preferences → AI to see the four sections (OpenRouter, OpenAI, Ollama Cloud, Azure OpenAI), each with its own Test / Save / Forget buttons.
OpenRouter (recommended cloud — one key, many models)
- Sign up at openrouter.ai. Add a few dollars credit; pay-as-you-go per token, no subscription.
- Create a key — Account → Keys → Create. Copy the
sk-or-v1-...string. - Paste in Notepatra — Settings → AI → OpenRouter section → API Key field → click Test. Green = good. Click Save.
- Pick "OpenRouter" in the backend dropdown. The model dropdown lists hundreds of models — type
claude,gpt,gemini,grok,kimi,qwen, etc. to filter.
OpenAI direct
- Get a key at platform.openai.com/api-keys. The string starts with
sk-(orsk-proj-for project keys). - Paste in Settings → AI → OpenAI section → Test → Save.
- Pick "OpenAI" in the backend dropdown. Curated list of the GPT-4o / GPT-5 / o-series families; type
gpt-5oro4to filter.
Azure OpenAI deployment
Azure exposes OpenAI through your tenant — you pay your Azure bill, not OpenAI directly. Setup is fiddlier because you address a deployment not a model.
- Get the three values from the Azure portal:
- Resource name — e.g.
my-openai-east(the part before.openai.azure.com). - Deployment name — what you called the deployment when you created it. NOT the same as the model name. Example:
gpt-4o-prod. - API version — e.g.
2024-08-01-preview. Use the latest stable from the Azure docs. - Key — Azure portal → your resource → Keys and Endpoint.
- Resource name — e.g.
- Settings → AI → Azure OpenAI — fill all four fields. Notepatra builds the URL
https://{resource}.openai.azure.com/openai/deployments/{deployment}/chat/completions?api-version={version}for you. - Test — green = the deployment answered. Save, then pick "Azure OpenAI" in the backend dropdown.
Ollama Cloud
Same Ollama models, served from Ollama's hosted infra. Useful when you want Ollama's catalog without the local RAM cost.
- Sign up at ollama.com and create an API key in your account settings.
- Settings → AI → Ollama Cloud — paste the key → Test → Save.
- Pick "Ollama Cloud" in the backend dropdown. The model list is the cloud catalog.
Per-provider key management
Every key slot has three buttons:
- Test — fires a probe at the provider's
/modelsendpoint with the key. Doesn't save anything; only validates. - Save — stores the key in your local Notepatra config file on your machine; it is never transmitted anywhere except to the AI backend you select. OS-keychain integration is a future candidate.
- Forget — wipes the stored key. Use this on shared machines before logging out.
Notepatra never uses a key from one provider against another. Selecting OpenRouter as the backend with no OpenRouter key set will show "OpenRouter key not set", even if your OpenAI key is configured.
Reasoning / thinking models
The Think checkbox in the AI dock toggles reasoning mode. Notepatra normalises the protocol per provider:
- OpenRouter — sends a unified
reasoningfield; works across Claude, o-series, Gemini, DeepSeek-R1, Qwen-QwQ. - Anthropic / Claude (via OpenRouter) — extended thinking with
thinking: { type: "enabled", budget_tokens: ... }. There is no direct Anthropic dropdown entry; Claude is reached through OpenRouter. - OpenAI o-series —
reasoning_effortfield. Note: o1/o3 don't accepttemperatureoverrides. - Local (Ollama, llama.cpp) — models that emit
<think>...</think>blocks (Qwen-QwQ, DeepSeek-R1) are auto-detected; Notepatra renders the thinking in a collapsed disclosure.
Troubleshooting
"Key invalid" — but it works in curl
Test button reports failure even though the same key works from a terminal.
- Trailing whitespace — copy-paste from a web page often appends a newline. Re-paste, then click in the field and press End to confirm no trailing characters.
- Wrong slot — OpenRouter keys (
sk-or-...) belong in the OpenRouter slot only. Pasting them in the OpenAI slot will fail because Notepatra won't cross-route. - Org / project header missing — some OpenAI project keys require an
OpenAI-Projectheader. Use a user key (startssk-notsk-proj-) if you don't want to manage that. - Rate-limited the test endpoint — the Test button hits
/models. If you've already burned through the free tier, the probe fails. Top up credit and retry.
Rate-limit errors / 429
Provider replies with HTTP 429.
- Free tier exhausted — most cloud providers cap requests-per-minute on free credit. Add credit or wait the reset window.
- Concurrent requests — Notepatra serialises requests per panel, but if you have multiple AI panels open and all hit the same provider, you can pile on. Close idle panels.
- No automatic retry — on HTTP 429 Notepatra surfaces a rate-limit message immediately ("Rate limited (HTTP 429) — too many requests; wait a moment and try again."). There is no exponential backoff; wait for the provider's reset window and retry manually.
Model not in dropdown after refresh
You expect a specific model and it's not in the list, even after clicking refresh.
- Curated list filter — Notepatra ships a curated list of known-good models per backend (v0.1.53+) for a clean UX. The dropdown is editable — type the full model id and press Enter to use any model the provider supports.
- Provider doesn't expose it on
/models— some preview models are key-gated and only appear on accounts with a flag enabled. Type the id manually. - Region / deployment scoping — for Azure, the deployment name is what you address; the underlying model is invisible. Make sure you have a deployment for the model family you want.
Cross-cutting troubleshooting
Backend-agnostic problems and their fixes.
AI panel says "thinking…" forever
- Streaming stalled — for local backends, a busy GPU or a context overflow can hang the stream. Click the Stop button; if that does nothing, restart the local server.
- Network timeout for cloud — Notepatra times out at 120 s of stream silence. If the provider is degraded, you'll see a timeout error after the wait.
- Reasoning model with huge budget — o1, Claude extended thinking, and DeepSeek-R1 can think for minutes on hard prompts. The "thinking" indicator is real progress; check the disclosure if visible.
Stop button doesn't stop
- Local backend mid-prompt-eval — Ollama and llama.cpp can ignore HTTP cancellation during the prompt-evaluation phase (before the first token is emitted). Stop is honoured once generation starts.
- Workaround — for stuck local servers, kill the process:
pkill -f ollama/pkill -f llama-server, then restart. - Cloud — the Stop button closes the SSE stream immediately; the backend may still be generating but you stop being charged for streamed tokens.
Coding mode sends but no tool calls fire
- Model lacks tools capability — the v0.1.55 capability probe should have hidden it. If you bypassed the probe by typing the id manually, the model may not emit tool calls regardless of prompt.
- llama.cpp without
--jinja— restart withllama-server --jinja ...so the chat template is applied. Without it, the model never sees the tool schema. - "Auto-attach open file" toggle off — Coding Mode without the file context is still functional, but the model can only act on what you paste. Tick the Auto-attach open file checkbox (the red-when-off / green-when-on lock-styled toggle in the AI dock) to share the current file.
Capabilities probe never returns
- Model not yet pulled all layers — first
/api/showon a model triggers full metadata read; takes a few seconds. Wait, then refresh. - Backend timeout — Notepatra times the probe at 5 s. If your local server is overloaded, the probe fails open (assumes no special caps) — switch to Chat mode to keep working.
Where Notepatra stores AI config
- Backend selection, model id, base URL, options — all settings persist to a single
config.json:~/.config/notepatra/config.jsonon Linux,%APPDATA%\Notepatra\config.jsonon Windows (the Roaming app-data dir),~/Library/Application Support/Notepatra/config.jsonon macOS. - API keys — stored in plaintext in the same
config.jsonabove (fieldsaiOpenRouterKey/aiOpenAIKey/aiOllamaCloudKey/aiAzureKey; no encryption, no separate key file; OS-keychain integration is a future candidate); they are never transmitted anywhere except to the AI backend you select. - Chat history —
~/.config/notepatra/chat-history/<sha1-of-workspace>.json(or platform equivalent), one JSON file per workspace (keyed by the SHA-1 of the workspace path), not per session. - Reset — close Notepatra, delete
config.json(in the dir above), then on next launch click Forget in each provider section if any keys remain. Restart for a clean slate.
OpenAI-compatible servers (user-configured)
The llama.cpp (GGUF) dropdown entry accepts a user-configured base URL. If you have installed any OpenAI-compatible HTTP server on your machine — anything that speaks the standard /v1/chat/completions protocol — paste its URL in Settings → Preferences → AI and Notepatra will use it through the llama.cpp dropdown entry. If the server requires an API key, paste it in the API Key field; it's sent as an Authorization: Bearer header. Such third-party servers are separate programs that you install, license, and operate independently of Notepatra — they are not bundled with Notepatra and Notepatra makes no representation about them.
AI Fix pipeline
The AI Fix button in JSON Tools / HTML Tools / Bracket Tools sends the broken content to Ollama with a strict prompt. Here's exactly what happens:
Request
POST http://localhost:11434/api/generate
Content-Type: application/json
{
"model": "<your selected model>", // whatever is picked in the model dropdown — NOT hardcoded
"prompt": "Fix ONLY the broken parts of this JSON. Make MINIMAL
changes. PRESERVE the original line order, key order, and
formatting. Do NOT reorder keys. Do NOT reformat. Return
ONLY the corrected JSON.\n\nBROKEN JSON:\n{...}",
"system": "You are a minimal-change JSON patcher. ... /no_think",
"stream": true,
"think": false,
"options": { "temperature": 0.3, "num_predict": 2048, "num_ctx": 4096 }
}
Response cleanup pipeline
Models don't always follow instructions. The response goes through a defensive cleanup pipeline before being displayed:
- Strip
<think>...</think>blocks — defensive regex strip for models that emit reasoning despitethink: false. - Strip markdown
```fences — if the response starts with```, find the first newline and the last fence and keep the middle. - Trim leading prose — find the first
{or[in the response and discard everything before. Handles "Here is the fixed JSON: {...}". - Format with Rust's
serde_json— if parseable, pretty-print with 4-space indent. Otherwise show raw cleaned text.
Why the strict prompt matters
Without explicit instructions, models love to reformat and reorder keys alphabetically. That's useless for a diff — every line looks different even when only one comma was missing. The strict prompt tells the model to preserve the original line order, key order, and indentation, and patch only the broken parts. Show Diff then shows just the actual fixes.
AI Assistant dock
Open: Ctrl+Shift+A, View → AI Assistant, or from the status bar. The panel is a persistent right-side dock (not an editor tab) — one conversation, preserved across tab switches. Layout:
- Backend dropdown — six entries in the standard build: Ollama, llama.cpp (GGUF), OpenRouter, Ollama Cloud, OpenAI, Azure OpenAI. The
notepatra-local-aicloud-free build ships only Ollama + llama.cpp. The llama.cpp entry accepts a user-configured base URL (Settings → Preferences → AI) so it can reach any OpenAI-compatible server you've installed (any OpenAI-compatible server — separate programs the user installs). API key edits inline. - Model dropdown — populated live from the backend's tags / models endpoint with a ↻ refresh button.
- Coding Mode toggle — flips the panel into 3-pane layout (file tree · editor · AI chat) and turns on agentic tools (see below).
- Show thinking checkbox — toggle reasoning for Qwen3 / DeepSeek-R1 / GPT-OSS / Hermes-3.
- Reset button — wipes chat history (in-memory + the on-disk per-workspace history file).
- Red close button (
×in#E81123) — closes the dock; chat session is preserved. - Chat area — user bubbles right-aligned; assistant bubbles left-aligned with the model name in the header. Per-code-block ⧉ Copy code buttons inside every response. Streaming stats render live (
tok / tok-s / s). - Quick actions (revealed by ▸ chevron when Coding Mode is OFF) — three rows of buttons:
- Row 1: Explain · Find Bugs · Refactor · Write Tests
- Row 2: Add Comments · Generate Docs · Optimize · Translate (Py ↔ JS)
- Row 3 (v0.1.40): Fix JSON · Fix HTML · Fix SQL — strict minimal-change patcher for the selection / file. Won't add fields, won't reformat, won't restructure.
- Insert at Cursor / Replace Selection / Copy — apply the last assistant response to the editor.
- Input bar — 📎 attach (image / PDF / DOCX / PPTX / XLSX / text), 🎙 voice (uses
arecord+ localwhisperCLI when installed), text field, Send, Stop.
Streaming tokens flow into the active assistant bubble in real time. Errors render as red error bubbles.
Workspace awareness
Every prompt to the AI dock automatically carries the right context — Notepatra figures out what the model needs:
- The active selection (or the full current file if no selection)
- Excerpts of every other open editor tab
- The workspace root path
- A flat listing of every file under the workspace (with
.git/node_modules/target/dist/__pycache__filtered out)
So the model can reference files you haven't opened yet — "import from utils.py" works even when utils.py isn't in a tab. The block is gated by intent so casual chat ("hi", "thanks") doesn't get spammed with workspace dump.
Persistent chat history (v0.1.39+)
Conversations survive app restart. Stored at:
~/.config/notepatra/chat-history/<sha1-of-workspace>.json
One file per workspace; switching workspaces loads the right history. Saves debounced 2 s, capped at 1 MB per workspace (oldest messages roll off). Reset deletes the on-disk file. Atomic write via .tmp + rename so a kill-9 mid-write never leaves a corrupt history.
Fix-intent detection (v0.1.40+)
Type fix my json / repair this html / the sql is broken in the chat input and the system prompt automatically swaps to a strict minimal-change patcher (same rules as Tools → JSON Tools → AI Fix). Models stop "improving" the input by adding fields, reordering keys, or restructuring.
Does NOT trigger on:
explain my json/describe this json/what is jsonshow me my json files/list all json files/find jsonteach me jsonfix my code(too generic — chat handles it normally)
Implementation lives in src/ai_intent.{h,cpp}. 51 assertions in test_ai_intent cover positive intents (case-insensitive, mixed phrasing), negatives (explain / describe / teach / show / list / find / grep), and edge cases (multi-line, @file mention, generic "fix my code").
Coding Mode — agentic tool-using AI (v0.1.35+)
Tick Coding Mode in the AI dock and Notepatra becomes an agent: the model can read your files, list directories, search, write files, and apply line-level edits — all on its own. The dock flips into a 3-pane layout (file tree · editor · AI chat).
Bottom segmented toggle — Chat / Compose / Agent (v0.1.61+)
The old top-of-panel Chat | Composer tabs are gone. v0.1.61 introduced a 3-segment toggle at the bottom of the AI dock — matching the iOS / Slack keyboard-accessory mental model that Continue.dev, Copilot Chat, and Cursor 3.0 all converged on:
- Chat — free-form conversation. The agent reads + searches but doesn't write.
- Compose — agent's write_file / apply_diff results land in the inline Edit Plan with per-file dry-run diffs. Nothing hits disk until you click Apply Selected or Apply All.
- Agent — write_file / apply_diff execute immediately (still subject to the path-safety / per-turn budget guards). The editor reloads the buffer automatically when a file the agent touched is currently open.
Per-hunk Stage / Revert from the editor gutter (v0.1.62+)
Click any green / red / blue change marker in the editor's git gutter (margin 3) and a hunk popup anchors at that line showing the before-vs-after content (an embedded DiffView) with three buttons:
- Stage hunk — pipes a unified-diff slice through
git apply --whitespace=nowarn --cached. Same safety rails as the AI tools (workspace anchor + credential deny-list + 5000-line hunk cap). - Revert hunk — reverses the patch direction so the working tree matches HEAD for just that hunk.
- Copy diff — drops the synthesized diff to your clipboard.
The Compare widget (Tools → Compare Files) gets the same buttons in a docked strip — one row per contiguous diff region (Hunk N/M · rows a–b · [Stage] [Revert] [Jump →]).
Marker-based merge resolution (v0.1.62+)
Files with UU (both-modified) status in the Git panel now show a Resolve button instead of the +/− shortcuts. Clicking it opens the merge helper widget which scans column-0 <<<<<<< / ======= / >>>>>>> markers and surfaces Take ours / Take theirs / Take both / Jump → buttons per conflict region, plus QScintilla annotation labels above each conflict. Full 3-way LOCAL/BASE/REMOTE merge editor is v0.2 scope; the marker-based path covers ~90% of conflicts.
Vision drag-and-drop (v0.1.61+)
Drop an image (PNG / JPG / WEBP / GIF / BMP) or document (PDF / DOCX / PPTX) onto the AI dock. If the active model is not vision-capable, you get a styled error bubble listing alternatives — local qwen2.5vl:7b / gemma3:4b, cloud claude-sonnet-4-6 / gpt-5 / gemini-2.5-flash. Detection:
- Ollama via the
/api/showcapability cache (returnscapabilitiesarray; conservative-false on empty cache so a slow Ollama doesn't silently drop your attachment). - Cloud via May-2026 prefix allowlist for Claude 3.5+, GPT-4o/4.1/5, Gemini 1.5+, Sonnet 4.x, etc.
Smart input gating + context guards (v0.1.61+)
The chat input + Send button now disable whenever the model dropdown is in a placeholder state — (detecting…), (Ollama offline), (no models installed), (API key required). State-specific placeholders explain why with concrete next steps (ollama serve, ollama pull qwen2.5-coder:7b, click ⚙). Additional guards:
- Coding Mode without a workspace → points you to File → Open Folder.
- Data Mode without a saved DB connection → points you to Manage Connections.
- Wrong-capability model in Coding mode → refusal card lists tool-capable alternatives.
Agentic tools
The agent gets up to 13 native tools — the five core file tools plus query_sql / csv_query / generate_chart and five read-only git_* inspection tools. AiTools::availableTools() registers all 13 unconditionally; the same array is sent on every Coding/Data turn. Every tool call shows up as an inline 🔧 toolname (args) → result card in the chat:
| Tool | What it does |
|---|---|
read_file(path, offset?, limit?, with_line_numbers?) | Read a text file from the workspace. Default emits N\t line-number prefix per line so the model can reference exact lines. v0.1.40: pass with_line_numbers=false to get raw content (recommended when feeding lines into apply_diff old_lines). |
list_dir(path) | List one level of entries with type (file/dir) and size. Filters .git / node_modules / target / dist / __pycache__ / .gradle / .idea / .vs. |
search(pattern, path?, regex?, glob?, case_sensitive?, max_matches?) | Find a string or regex across the workspace. Returns up to 50 (default) / 200 (max) matches with file path, line, column, and a snippet. Same heavy-dir skip-list as the file tree. |
write_file(path, content, mode?) | Create or overwrite a text file. Modes: overwrite (default) / create (fails if exists, returns error_kind: exists) / append. Auto-creates parent directories inside the workspace; refuses paths matching the credential deny-list (suffixes .pem / .key / .pfx / .p12 / .tfvars / .tfstate; filenames id_rsa* / authorized_keys / known_hosts / .env / secrets.json). 5 MB content cap. After success the file auto-opens in a new tab — or the buffer reloads if it's already open. |
apply_diff(path, hunks) | Atomic line-level edits. Each hunk has old_start_line + old_lines (expected current text) + new_lines (replacement). Two-phase apply: validates ALL hunks against the live file first → if any drifted, returns error_kind: conflict and nothing is written. Otherwise hunks apply in reverse-line-order so earlier indices stay stable. v0.1.40 three-tier match: strict → strip read_file's N\t prefix from old_lines → .trimmed() comparison. Relaxed tiers still apply but emit result.warnings so the agent self-corrects on the next read. Atomic write via .tmp + std::rename. |
query_sql(connection_name, sql, max_rows?, confirm?) | Run SQL against a saved database connection. SELECT-only by default (also WITH / EXPLAIN / PRAGMA / SHOW / DESCRIBE); INSERT / UPDATE / DELETE / DDL require confirm:true. Returns up to 100 rows by default (hard max 500). Most useful in Data Analyst Mode — see below. |
csv_query(file_path, sql, max_rows?, max_load_rows?) | Load a workspace CSV into in-memory SQLite (table csv) and run SQL against it. Default loads up to 250,000 rows; returns up to 500. |
generate_chart(...) | Emit a Vega-Lite chart spec for the assistant to render. On Lite the result paints as a "Chart rendering requires the Charts Pack" card; full rendering needs the Charts Pack (WebEngine). |
git_status / git_diff / git_log / git_branch_list / git_show | Read-only git inspection (implemented in src/git_tools.cpp; the QProcess verb list is hard-coded so there is no path through these to mutate the repo). |
Three-layer path security
Every tool call goes through resolveSafePath:
- Workspace anchor + canonicalize. Relative paths resolve against the workspace root; absolute paths are accepted only if they canonicalize back inside it. This is what refuses
../../../../etc/passwd,~/.ssh/,~/.aws/,~/.gnupg/,~/.netrcand the like — they fall outside the workspace anchor (error_kind: outside_workspace), not via the deny-list below. Also catches symlink-to-secrets attacks. - Hardcoded credential deny-list (
isHardDenied()). Refuses paths by suffix —.pem/.key/.pfx/.p12/.tfvars/.tfstate— or by filename —id_rsa/id_ed25519/id_ecdsa/id_dsa/authorized_keys/known_hosts/.env(and*.env/*.env.*) /secrets.json. Applied to the candidate path itself, so a mkpath chain can't sneak one through (error_kind: denied). - Structured errors. Refusals come back as
error_kind: outside_workspace | denied | not_found | exists | binary | too_large | conflict | malformed_args | io_error— the model knows what to fix.
Per-turn budget (Hard cap)
Hard cap of 25 tool calls per user turn to prevent runaway loops on confused models. When exhausted, the agent receives: "Tool-call budget exhausted (25 calls this turn). Stop and summarise what you've found."
Tool-call wire format
Notepatra uses each backend's native tool-call protocol:
- Ollama —
/api/chatwith thetoolsarray. Some open-weight models also need--jinja(we surface a friendly warning when the response shape suggests this). - llama.cpp —
llama-serverwith--jinjarequired. OpenAI-compatibletool_callsin the response. - OpenAI-compat (OpenRouter, OpenAI, Azure OpenAI, or any user-configured OpenAI-compatible server) — standard SSE streaming with
finish_reason: tool_calls.
v0.1.40 surfaces malformed tool-call JSON as a structured error_kind: malformed_args result back to the model — so a model that emits unescaped quotes in arguments gets a clear "re-emit with valid JSON" message + raw-args preview, instead of silently passing empty args downstream.
Models that work well in Coding Mode
Notepatra has a model allowlist for Ollama (other backends always send tools and trust the server's support detection). Confirmed working:
- Qwen3 / Qwen3.5 — best small-model tool-call support today.
- Llama 3.1+ (3.1 / 3.2 / 3.3) — first Meta line with native tool calls.
- Hermes-3, Mistral-Nemo, Granite 3+, GPT-OSS, Command R / R+.
- Cloud via OpenAI-compat: GPT-4o / GPT-5, Claude 3.5+ / Sonnet 4+, Gemini 1.5+ via OpenRouter.
Models not recommended: phi-3-mini / phi-3.5 (no tool support), gemma-2-2b (sometimes hallucinates tool calls), tinyllama, llama 3 base.
Data Analyst Mode (v0.1.43+)
Tick the new Data checkbox in the AI dock header (next to Coding) and the AI assistant becomes a data analyst: it can query attached CSVs, run SQL against your saved database connections, and emit live charts inline in the chat. Mutually exclusive with Coding Mode so the panel stays focused.
What changes when Data Mode is on
- Header shows an orange accent — the title reads "AI · DATA" with orange (
#FF9F43) text and a 2px bottom border (the band background stays the normal chrome colour) — so it's unmistakable which mode is active. - A Manage Connections… button appears under the model picker.
- Attached CSVs get a structured digest instead of a raw text dump (delimiter sniff, header probe, per-column type — Integer / Real / Boolean / Date / DateTime / Text — null counts, ranges, head + tail rows, capped at 4 KB).
- The system prompt swaps to a data-analyst persona that emits Findings → Method → Suggested follow-ups structure.
- Two new agentic tools (below) are attached to the request alongside
read_file/list_dir/search. - If you have a
.notepatra/data-analyst.mdin your workspace, its contents are auto-prepended as a "Project data context" layer (capped at 8 KB).
The two new agentic tools
| Tool | What it does |
|---|---|
csv_query(file_path, sql, max_rows?, max_load_rows?) | Loads a workspace CSV into in-memory SQLite (table name csv, column names from the header) and runs your SQL. Default loads up to 250,000 rows; default returns up to 500. Lets the model ask "SELECT category, SUM(amount) FROM csv WHERE order_date >= '2026-04-01' GROUP BY category ORDER BY 2 DESC" instead of trying to mentally scan a million-line file. |
query_sql(connection_name, sql, max_rows?, confirm?) | Runs SQL against a saved connection. SELECT-only by default (also: WITH / EXPLAIN / PRAGMA / SHOW / DESCRIBE). INSERT / UPDATE / DELETE / DDL require confirm:true after the user explicitly approves — no implicit mutations. Returns up to 100 rows by default (hard max 500 — the model must raise max_rows to get more). |
Live charts inline in the chat
v0.1.64+ note: charts now ship behind the optional charts pack. On a default (lite) install, the AI's generate_chart tool result paints as a Chart rendering requires the Charts Pack card with two buttons — [Install charts pack] (opens GitHub Releases with the matching -full asset for your OS — on Linux/Windows; on macOS the -full DMG adds the DuckDB engine only, with no inline Vega rendering) and [View JSON instead] (shows the raw Vega-Lite spec in a fenced code block). See Lite vs Full for the upgrade paths. The flow described below is what you see once you're on the Full flavor.
Charts the model emits as a fenced ```chart block render inline on Lite via QtCharts; only generate_chart tool results (Vega-Lite) need the Charts Pack (Full / WebEngine).
When a visualization clarifies the answer, the model emits a fenced ```chart block with a small JSON spec. Notepatra parses each one and renders it inline natively via QtCharts (ChartRender::renderFromSpec) — no WebEngine, so these fenced charts work on both the Lite and Full builds. (Only the generate_chart tool's Vega-Lite output goes through the embedded QtWebEngine + vega-embed path, which needs the Charts Pack / Full build.) Example:
```chart
{
"type": "bar",
"title": "Revenue by category, last 30 days",
"x": "category",
"y": "revenue",
"data": [
{"category": "electronics", "revenue": 284921.50},
{"category": "books", "revenue": 52183.25},
{"category": "home", "revenue": 98442.10}
]
}
```
Supported types rendered natively by QtCharts: line, bar, pie, scatter, area, horizontal-bar, stacked-bar, stacked-horizontal-bar, grouped-bar, donut, histogram, boxplot. (Vega-Lite-only types — heatmap, density, regression-line, faceted-bar, error-bar — fall back to a "Chart rendering requires the Charts Pack" stub on Lite.) Theme-aware. Category-aware axes for string-valued X columns; numeric axes for numeric X. Malformed JSON falls back to displaying the spec as a code block — nothing breaks.
Database connection manager
Click Manage Connections… (visible only when Data Mode is on) to add a new connection. The dialog has a Preset dropdown at the top — pick one and the form fills with sensible defaults for that database type so you only edit what's specific to your server.
Available presets (v0.1.66+):
- SQL Server (localhost, ODBC) — Driver =
QODBC, Host =127.0.0.1, Port =1433, Database =master, Username =sa, Options =DRIVER={ODBC Driver 18 for SQL Server};Encrypt=no - SQL Server (Notepatra local Docker, port 14330) — pre-configured for the bundled
sql-server-localDocker harness; Port =14330(not 1433, so it coexists with any SQL Server already on the default port). Pre-fills everything except the password. - SQL Server Express (named instance, ODBC) — Host =
localhost\SQLEXPRESS, Port = default (named instances use the SQL Browser service), Options includeTrusted_Connection=yesfor Windows Auth - Azure SQL Database (ODBC) — Host =
yourserver.database.windows.net, Options includeEncrypt=yes;TrustServerCertificate=no(Azure requires TLS) - PostgreSQL (localhost) — Driver =
QPSQL, Port =5432, Database =postgres, Username =postgres - MySQL / MariaDB (localhost) — Driver =
QMYSQL, Port =3306, Database =mysql, Username =root - SQLite (file on disk) — Driver =
QSQLITE, Browse… picker focused on Database for the .db path - DuckDB (file or :memory:) — Driver =
DUCKDB, Database =:memory:(also accepts a .duckdb / .csv / .parquet / s3:// path) (ships in the Full download on every platform; the Lite default download reports "support not compiled in")
Under the form, a hint label paints in green when the Qt SQL plugin for the chosen driver is present (with a usage tip — e.g. "Named instances use the SQL Browser service — leave Port at default") or amber with the exact per-OS install commands when the plugin is missing.
Connections are saved to ~/.config/notepatra/db-connections.json (or platform equivalent). The dialog also has a Test button that opens + closes the connection without committing the record — green tick on success, red driver error on failure.
How to connect — step by step (v0.1.66+)
SQL Server — local Docker for testing
The fastest way to play with SQL Server is the bundled Docker harness:
# 1. Spin up MS SQL Server 2022 + seed a NotepatraTest database
bash scripts/sql-server-local-setup.sh
# 2. Linux only — install Microsoft's ODBC Driver 18:
curl https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
curl https://packages.microsoft.com/config/ubuntu/24.04/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev libqt5sql5-odbc
# 3. Restart Notepatra. The 'sql-server-local' connection is already
# registered — open Data Mode → Manage Connections to see it.
# Tear down later:
bash scripts/sql-server-local-setup.sh --teardown # stop + remove container
bash scripts/sql-server-local-setup.sh --wipe # also drop the data volume
The script creates a NotepatraTest database with customers, products, and orders tables already populated, plus a sql-server-local entry in your db-connections.json. After installing the ODBC driver, you can ask the Data Analyst:
- "Show top-3 customers by total spend from the sql-server-local connection"
- "List the schema of dbo.orders"
- "What's the average order value per country?"
SQL Server — connecting to an existing server (Windows / macOS / Linux)
- In Manage Connections, pick the SQL Server (localhost, ODBC) preset to pre-fill the form.
- Change Host to your server's address. For named instances (e.g. SQL Express):
SERVER\INSTANCEand set Port to default. - For SQL Authentication: enter your SQL login + password.
- For Windows Authentication (domain account / current Windows user, Windows only): clear Username, leave Password empty, and add
;Trusted_Connection=yesto Options. - For TLS-required servers (Azure, modern on-prem): change Options to
DRIVER={ODBC Driver 18 for SQL Server};Encrypt=yes;TrustServerCertificate=no. - Click Test. If green, click Save Changes then OK.
If Test fails with "data source name not found and no default driver specified", your DRIVER={…} string doesn't match a driver actually installed. Run odbcinst -q -d (Linux/macOS) or ODBC Data Source Administrator (Windows) to see which driver names are available — use the exact name in your Options string.
PostgreSQL — local + managed (RDS / Cloud SQL / Neon / Supabase)
- Pick the PostgreSQL (localhost) preset.
- For a local Postgres, leave everything at the defaults and enter your password.
- For a remote / managed Postgres, set Host to your endpoint (e.g.
myapp.abc123.us-east-1.rds.amazonaws.com), Database to your specific DB name (RDS doesn't acceptpostgresas default). - For TLS-required servers (any managed PG should require TLS), set Options to
sslmode=require(orsslmode=verify-full;sslrootcert=/path/to/ca.pemfor cert pinning). - Unix-socket connections (lower latency on the same host): leave Host empty, set Options to
host=/var/run/postgresql.
MySQL / MariaDB
- Pick the MySQL / MariaDB (localhost) preset.
- For local servers, defaults are fine — set your password and the database name.
- For RDS / PlanetScale / managed MySQL, set Options to
SSL_CA=/etc/ssl/certs/ca-certificates.crt;MYSQL_OPT_CONNECT_TIMEOUT=10. - For Unix-socket: clear Host, add
UNIX_SOCKET=/var/run/mysqld/mysqld.sockto Options.
SQLite — file-based
- Pick the SQLite (file on disk) preset — focus jumps to Database.
- Click Browse… and pick the .db / .sqlite / .sqlite3 file (or type a path — the file is created if it doesn't exist).
- No host / port / username / password — SQLite is file-based.
DuckDB — files, S3, in-memory
DuckDB ships in the Full prebuilt download (libduckdb v1.1.3 bundled alongside the binary) on every platform. On the Lite (default) download the DuckDB connection reports "support not compiled in" — switch to the Full download to use it.
- Pick the DuckDB (file or :memory:) preset — Database defaults to
:memory:. - The Database field is multi-mode — point it at:
:memory:— ephemeral DB/path/to.duckdb— persistent DuckDB file/path/to.csv,/path/to.parquet,/path/to.json— DuckDB reads them directly (no import step)s3://bucket/key.parquet— S3 via DuckDB's httpfs extension; fill Options withregion;access_key_id;secret;session_token
- No host / port / username / password — DuckDB runs in-process via the native libduckdb engine.
Driver availability per OS
| Driver | Linux (Debian/Ubuntu) | macOS (Homebrew) | Windows |
|---|---|---|---|
| QSQLITE | Built into Qt — always available | Built into Qt — always available | Built into Qt — always available |
| QPSQL (PostgreSQL) | sudo apt-get install libqt5sql5-psql | bundled in brew install qt@5 | Bundled with the Notepatra Windows release |
| QMYSQL (MySQL/MariaDB) | sudo apt-get install libqt5sql5-mysql | bundled in brew install qt@5 | Bundled with the Notepatra Windows release |
| QODBC (SQL Server) | sudo apt-get install libqt5sql5-odbc unixodbc-dev msodbcsql18 (see MS install guide for the package repo setup) | brew tap microsoft/mssql-release && HOMEBREW_ACCEPT_EULA=Y brew install msodbcsql18 unixodbc | Bundled with the Notepatra Windows release (Microsoft ships ODBC drivers with Windows itself) |
| DUCKDB | Bundled in the Full prebuilt download (libduckdb v1.1.3 alongside the binary); runs in-process. Lite (default) reports "support not compiled in." | Bundled in the Full prebuilt download (libduckdb v1.1.3 alongside the binary); runs in-process. Lite (default) reports "support not compiled in." | Bundled in the Full prebuilt download (libduckdb v1.1.3 alongside the binary); runs in-process. Lite (default) reports "support not compiled in." |
Troubleshooting
- "Driver not loaded" — the Qt SQL plugin for your driver isn't installed. The Manage Connections dialog now paints an amber install-command hint under the form when this happens; copy-paste the command for your OS.
- "data source name not found" (QODBC) — your Options
DRIVER={…}string references an ODBC driver that isn't installed. Linux/macOS:odbcinst -q -dlists installed drivers. Windows: ODBC Data Source Administrator (in Administrative Tools). Use the exact name in your Options. - "Server certificate not trusted" — add
TrustServerCertificate=yesto QODBC Options (test environments only), or install the server's CA cert. - "FATAL: password authentication failed" (QPSQL) — usually a
pg_hba.confmismatch. For local-only testing, addhost all all 127.0.0.1/32 md5at the bottom ofpg_hba.confandpg_ctl reload. - "Can't connect to MySQL server on 'localhost'" — MySQL often binds Unix-socket-only by default. Either start it with
--bind-address=127.0.0.1or use socket-mode (clear Host, addUNIX_SOCKET=…to Options).
Browse Schemas… (Database tree dialog, v0.1.55)
Click Browse Schemas… in the Data Analyst panel to open a tree view of every saved connection. Schema introspection is lazy — clicking a connection node loads its schemas; clicking a schema loads its tables; clicking a table loads its columns + types. Supports SQLite (via sqlite_master), DuckDB (via the native listTables / describeTable wrappers), and any database with INFORMATION_SCHEMA (PostgreSQL, MySQL, SQL Server). Live filter input narrows the tree by name. Right-click any node:
- Send schema to AI — pins the table's column list to the next prompt as authoritative schema context.
- Sample 10 rows (clipboard) — copies
SELECT * FROM <table> LIMIT 10to the clipboard. It does not run the query or open a results pane. - Copy SELECT * — drops a fully-qualified
SELECT * FROM schema.tableinto your clipboard.
Honest limitation: connection passwords are obscured at rest (XOR + base64), NOT real encryption. This is "don't show plaintext to people walking past my screen", NOT "survives a stolen laptop." For production secrets, use OS keychain / .pgpass / instance-role IAM. OS-keychain integration is a future candidate.
Project-level data context: .notepatra/data-analyst/ (v0.1.55)
Drop one or more markdown / SQL files into a .notepatra/data-analyst/ directory in your workspace and Notepatra auto-prepends their contents to the system prompt as a "Project data context" layer when Data Mode is on. Per-workspace, version-controllable. Conventions:
instructions.md— high-level analyst guidance ("treat NULL amounts as 0", "fiscal year matches calendar")data-dictionary.md— column-by-column meaning for tricky tablesbusiness-rules.md— domain rules, edge cases, segment definitionskpis.md— definitions of revenue / churn / retention / ARR / LTV in your businesssample-queries.sql— reference SQL the model can adapt- any other
*.md/*.sqlfiles in the directory get loaded too
Caps: each file is read up to 16 KB and the combined context is gathered up to 64 KB, but the result is then truncated to 8 KB total (with a [...truncated] marker) before it reaches the system prompt — so only the first ~8 KB of your combined project data context actually lands in the model's prompt. Curate accordingly: put the most important guidance first. The Welcome card surfaces the loaded-files count so you know context was picked up. The legacy single-file .notepatra/data-analyst.md is also still supported.
- The `orders` table joins `customers` on `customer_id`.
- Treat NULL in `amount` as 0 (legacy import bug, never backfilled).
- `rate` is a percentage stored 0–1, not 0–100. Don't average it.
- Q1 = Jan-Mar, fiscal year matches calendar.
Then ask "show me last quarter's top-revenue customers" and the model already knows the schema and quirks.
Model capability gating
Multi-table SQL and chart-spec emission are harder than read_file. AiTools::modelCapableOfDataAnalysis() allowlists frontier cloud models (Claude 4.x, GPT-4 / 5, Gemini 2.x, DeepSeek-V3) and local models ≥7B params from strong families (qwen2.5-coder, llama3.x, mistral-large). When you toggle Data Mode on with a model below the bar (e.g. llama3.2:1b), the panel shows an inline orange banner suggesting capable alternatives. The mode still works — the banner is the heads-up, not a hard block.
What's NOT in v0.1.43 (deferred)
- PPT / image data extraction. Attaching a
.pptxcurrently falls back to the existing text extractor; chart images aren't OCR'd into structured data. v0.1.44+ candidate. - Real OS-keychain integration for connection passwords. The XOR obscuration is a placeholder. v0.1.44+ candidate.
Thinking models
Qwen3 / DeepSeek-R1 and other "thinking" models emit <think>...</think> reasoning blocks before the actual answer. For JSON Tools, this breaks the parser (the thinking block isn't valid JSON). Notepatra's cleanup pipeline strips <think> tags three ways:
- Passes
think: falsein the/api/generaterequest body (honored by modern Ollama) - Appends
/no_thinkto the system prompt (honored by some models as a slash-command) - Regex-strips
<think>...</think>from the final response as a defensive backup
For the AI Assistant chat, you can toggle Show thinking to see the reasoning if you're curious.
Vision models & file attachments
The 📎 attach button accepts any file type. What happens depends on the kind:
| File kind | Handled how |
|---|---|
| 🖼 Images (png/jpg/webp/gif/bmp) | Loaded as QImage, downscaled to max 1280px, re-encoded as PNG, base64-encoded, passed in the images field of /api/generate. Recognised local vision models (prefix allowlist: llava, llama3.2-vision, qwen2.5vl / qwen2.5-vl, gemma3, minicpm-v, moondream, mistral-small3.1) actually see the image; cloud Claude 3.5+ / GPT-4o-4.1-5 / Gemini are also vision-capable. If the selected model is not vision-capable, the image attachment is refused up front with an error bubble that names the model and suggests alternatives — it is not silently dropped. |
pdftotext -layout via QProcess (requires poppler-utils), extracted text appended to the prompt as context, capped at 100 KB. | |
| 📘 DOCX / ODT | unzip -p file.docx word/document.xml, XML tags stripped, appended to prompt. |
| 📙 PPTX | unzip -p file.pptx ppt/slides/slide1.xml, XML stripped, appended (first slide only for now). |
| 📗 XLSX | unzip -p file.xlsx xl/sharedStrings.xml, appended. |
| 📄 Text / code (*.txt / *.md / *.json / *.py / *.cpp / *.js / ...) | Read raw as UTF-8, capped at 100 KB, appended as context. |
| Anything else | Attempted as text (UTF-8). |
AI Interaction Log
Audit exactly what your AI did — transparency, not just a promise. Every request and response to any AI backend is recorded to a local SQLite log you can open and read. That covers both local backends (Ollama, llama.cpp) and cloud backends (OpenRouter, OpenAI, Azure OpenAI, Ollama Cloud), as well as Noter's AI Extract.
Each entry stores the timestamp, backend, model, the full prompt and response, token counts, and latency. Open it from Features → AI Interaction Log…
What the viewer gives you
- Filters — narrow the list by backend, model, or text.
- Export JSON — dump the (scrubbed) entries for your own records or review.
- Prune now — clear the log immediately rather than waiting for the 7-day window.
The underlying database is a plain SQLite file under your per-user config directory (ai-logs/interactions.db) — nothing proprietary, nothing remote. You can audit it with any SQLite tool, not just the in-app viewer.
Noter — meeting notes
Noter is a local-first meeting-notes workspace built into Notepatra. It uses a simple two-pane layout — a notes list on the left and an editor on the right. There are no accounts and no bots: your notes are saved as plain files under ~/Documents/Notepatra/Noter/, so they're yours to read, back up, or sync however you like.
AI Extract
Press Ctrl+Alt+E to run Extract on the current note. It pulls a concise summary plus four structured lists — action items, decisions, questions, and risks — and writes the summary back into the note. Extract also schedules real reminders, parsing natural-language times such as "10am tomorrow" or "next Monday at 3pm" into actual due dates. If a reminder it's about to create already exists, it flags the duplicate rather than scheduling it twice. (Like every AI action in Notepatra, an Extract run is recorded in the AI Interaction Log.)
Reminders
Set a reminder on any note — or straight from an Extract run — and it appears in a central Reminders list in the Noter sidebar, grouped into Overdue, Today, This week, and Later. Click a reminder to open the note it's bound to; right-click to reschedule or delete it. A desktop notification fires at the due time while Notepatra is running (any tab — Noter doesn't need to be open); reminders missed while it was closed arrive as one summary at next launch.
Diagram tool (.npd)
The Diagram tool authors flow charts, ER diagrams and system designs from a small purpose-built text DSL (.npd). It's text-first: the .npd source is the single source of truth and the canvas is a live projection of it, so undo/redo, version control and AI editing all work on plain text. Open it from the Built-in Tools toolbar ("Diagram", next to Noter) or Features → Diagram — Flow / ER / System (.npd). The tab is a split view: .npd source on the left, live canvas on the right. Renders in every build — as of v0.1.103 the diagram is drawn by a native Qt renderer (QPainter), so it works in the default binary on every platform, including macOS Apple Silicon and the Windows installer, with no embedded browser and no separate "Full" download.
Three ways to create one
- AI Generate — describe the diagram in plain English ("a login flow with validation; users in a database"). A local Ollama model returns
.npd, shown in an editable review pane. Nothing touches the canvas until you click Insert — review at every step, undo/redo afterward. - New — start from a Flow, ER or System template and tweak it.
- Write
.npdin the left pane — the canvas re-renders as you type. Or Import Mermaid to convert an existing Mermaid flowchart.
A Help button in the toolbar opens an in-tool cheat-sheet, and samples/diagram_showcase.npd demonstrates every element.
The .npd syntax
One statement per line; # starts a comment. Shapes:
node a (Start) pill — start / end
node b [Process] box — process (default)
node c {Valid?} diamond — decision
node d ([Users]) cylinder — database
icon db :database "DB" rich-icon node
A rich icon set — ~55 hand-drawn icons (covering system / ER / flowchart vocabularies: database, server, user, patient, hospital, document, cloud, gear, queue, cache, api, lambda, container, kubernetes, loadbalancer, firewall, mobile, browser, table, process, decision, chart and more) with ~150 aliases so familiar names resolve automatically (postgres→database, k8s→kubernetes, …). Arrows: a -> b (directed), a -> b : label (labelled — write the colon with a leading space), a <-> b (bidirectional), and chains a -> b -> c (expands to a→b, b→c; a trailing : label rides the last hop). Optional colour (v0.1.104): add a #hex or common colour name after a node's shape — node proc [Process] #1565c0, node start (Start) green — and the renderer derives a readable border and auto-contrast label text; leave it off and the node keeps the palette, so diagrams stay monochrome by default. Keep shape text short and put detail on hover: node dash [Dashboard] :: "Loads the saved session". Set diagram flow|er|system, title "…", palette clay|ocean|forest|mono, and textbox "caption".
Canvas & export
Drag to pan, scroll to zoom, double-click to fit. Export the rendered diagram with the Export button: PNG / JPEG / PDF on every build, plus SVG / HTML where your Qt has the Svg module and WebP where it has the WebP image plugin — the menu shows exactly what your build supports, and unavailable formats are hidden rather than writing a broken file. The headless npd_render <file.npd> <out.{png|jpeg|webp|svg|pdf|html}> utility renders any .npd without launching the GUI (output format taken from the extension) — it is a build-from-source developer utility, not packaged in releases.
Keyboard shortcuts
File
| Ctrl+N | New |
| Ctrl+O | Open |
| Ctrl+S | Save |
| Ctrl+Shift+S | Save As |
| Ctrl+Alt+S | Save All |
| Ctrl+W | Close tab |
| Ctrl+P |
Edit
| Ctrl+Z | Undo |
| Ctrl+Y / Ctrl+Shift+Z | Redo |
| Ctrl+X / Ctrl+C / Ctrl+V | Cut / Copy / Paste |
| Ctrl+A | Select all |
| Ctrl+D | Duplicate line |
| Ctrl+Shift+K | Delete line |
| Ctrl+/ | Toggle line comment |
| Ctrl+Shift+U | UPPERCASE selection |
| Ctrl+U | lowercase selection |
| Ctrl+Shift+↑ / Ctrl+Shift+↓ | Move line up / down |
Search
| Ctrl+F | Find |
| Ctrl+H | Replace |
| F3 / Shift+F3 | Find next / previous |
| Ctrl+G | Go to line |
| Ctrl+B | Go to matching brace (swivels between open/close) |
| Ctrl+F2 | Toggle bookmark |
| F2 | Next bookmark |
| Shift+F2 | Previous bookmark |
View / Navigation
| Ctrl+= / Ctrl+- | Zoom in / out |
| Ctrl+0 | Reset zoom |
| Ctrl+Tab | Next tab |
| Ctrl+Shift+Tab | Previous tab |
| Ctrl+Shift+E | Toggle File Explorer sidebar |
| Ctrl+Shift+A | Toggle AI Assistant dock |
| Ctrl+Shift+G | Open Project Search |
| F11 | Full screen |
Macro
| Ctrl+Shift+M | Start macro recording |
| Ctrl+Shift+T | Stop macro recording |
| Ctrl+Shift+P | Play last macro |
Command-line flags
notepatra [options] [file1] [file2] ...
Options:
-h, --help Show help and exit
-v, --version Show version and exit
-n, --new Open a new window, don't restore session
--line N Go to line N in the first file
--theme NAME Use theme: Light, Dark, Monokai
Examples:
notepatra Open with last session restored
notepatra file.py Open a file
notepatra --line 42 file.py Open at line 42
notepatra --theme Dark Start in dark mode
notepatra *.json Open multiple files
Single instance. As of v0.1.114, launching notepatra file.txt while Notepatra is already running hands the file to the existing window (raised and focused) and exits — after the running instance proves it's alive, so an open can never be silently swallowed. If the running instance is hung or busy for more than ~3 seconds, you get a visible temporary window with just your files instead: it never touches your saved session, and it prompts Save / Discard / Cancel per modified tab when closed. --new opens the same kind of session-independent window on purpose. --line N always targets the first file listed. Files that don't exist produce a notice in the running window rather than disappearing silently.
Config file layout
All persistent state lives under:
| OS | Path |
|---|---|
| Linux | ~/.config/notepatra/ (honours $XDG_CONFIG_HOME) |
| macOS | ~/Library/Application Support/Notepatra/ |
| Windows | %APPDATA%\Notepatra\ (Roaming) |
Files inside that directory
config.json— editor preferences: theme, font, tab width, word wrap, line numbers, etc.session.json— open tabs, cursor positions, window geometryrecovery/— auto-save backups of unsaved buffers (every 5s by default, configurable 1–300s)plugins/— user-installed external pluginsai-logs/interactions.db— the AI Interaction Log (SQLite; on by default, auto-pruned after 7 days)
Build from source
Dependencies
- Qt5 (5.15.2 or newer) —
qtbase5-dev,libqt5widgets5,libqt5core5a,libqt5network5,libqt5printsupport5 - QScintilla 2.14.1+ —
libqscintilla2-qt5-dev - Rust (1.70+) — via
rustup - CMake 3.16+
- C++17 compiler — gcc 9+, clang 10+, or MSVC 2019+
One-liner (Linux/macOS)
git clone https://github.com/singhpratech/notepatra.git
cd notepatra
./build.sh
Add --tests to also build and run the regression suite via CTest.
Manual CMake
cd notepatra
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON
cmake --build . -j$(nproc)
./notepatra --version
Windows (PowerShell, MSVC)
# 1. Install Qt5 via aqtinstall or install-qt-action
# 2. Build QScintilla from Riverbank source via qmake + nmake
# 3. Then:
cd notepatra
mkdir build; cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release
See .github/workflows/build.yml for the exact CI command sequence.
Verifying releases
Every release ships with:
- SHA-256 checksums in
SHA256SUMS - Cosign keyless signatures (Sigstore + Rekor transparency log) —
.sig+.pemper asset - SLSA build provenance attestations cryptographically linking each binary to the commit + workflow + runner
SHA-256
curl -sL -O https://github.com/singhpratech/notepatra/releases/latest/download/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing
Cosign verify
cosign verify-blob \
--certificate-identity-regexp '^https://github.com/singhpratech/notepatra/' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
--certificate notepatra-linux-x64.tar.gz.pem \
--signature notepatra-linux-x64.tar.gz.sig \
notepatra-linux-x64.tar.gz
SLSA attestation
gh attestation verify notepatra-linux-x64.tar.gz --owner singhpratech
Full threat model and disclosure policy in SECURITY.md.
Troubleshooting
Notepatra opens but no text renders / white-on-white
Likely a lexer palette bug. Try Settings → Theme → Light then back to your theme. If it persists, file a bug with your OS + theme + a screenshot.
AI Fix doesn't do anything
- Check the Ollama Status bar at the top of the JSON Tools panel — is the dot green?
- If red:
ollama servein a terminal, check port 11434. - If green but no response: make sure you've pulled at least one model:
ollama list. - Check Notepatra's stderr for the streaming tokens / error.
Windows: "This program can't start because ... was not found"
The NSIS installer bundles Qt DLLs, but the portable .zip depends on the Visual C++ Redistributable. Install the latest VC++ Redistributable and relaunch.
macOS: "Notepatra can't be opened because it is from an unidentified developer"
macOS Gatekeeper. Right-click the .app, choose Open, then Open again in the warning dialog. Or run xattr -cr Notepatra.app to clear the quarantine attribute.
Linux ARM64 binary doesn't launch
Make sure the file is executable: chmod +x notepatra. Check Qt5 is installed for your architecture.
"Another Notepatra is running but not responding — opened a temporary window"
You double-clicked a file while the running Notepatra was busy (a huge session restore, a multi-GB file load) or genuinely hung. Rather than letting the open vanish, v0.1.114+ opens your files in a temporary window. Your saved session is untouched; the temporary window prompts Save / Discard / Cancel for any unsaved edits when you close it. Once the main window is responsive again, just close the temporary one — or keep working in it and save your files explicitly. If this happens on every double-click, the main instance is stuck: close or kill it and relaunch.
A file I opened never appeared (older versions)
Versions before v0.1.114 could silently swallow an open on Windows — non-ASCII paths (accents, CJK) mangled by the ANSI codepage, double-clicks during startup, or a hung background instance holding the single-instance pipe. All of these are fixed in v0.1.114: opens are acknowledged end-to-end, every failure produces a visible notice, and a stuck instance falls back to a temporary window. If you still see a silent open on v0.1.114+, that's a bug we want — please file it with the path and platform.
FAQ
Is Notepatra a port of another editor?
No. Notepatra is its own application — a native Qt5 + QScintilla editor with an original C++17/Rust core for the hot paths (memory-mapped file I/O, Aho-Corasick search, Myers diff, the formatters). The editing surface is QScintilla — the mature Scintilla engine, the same one Notepad++ is built on — so folding, brace matching and lexing are battle-tested rather than reinvented; everything around it (the AI dock, the tools, the Rust core, the UI) is Notepatra's own. It builds from a single codebase for Linux x64 / ARM64, macOS Apple Silicon, and Windows x64.
What's the difference between the Lite and Full builds, and which do I get?
The default download is Lite: the complete editor — all 82 lexers, the AI dock, diagrams, formatters, Git, terminal — with no browser engine bundled, which is why the bare binary stays ~12 MB. Full bundles the DuckDB engine on every platform, and — on Linux and Windows — adds QtWebEngine so the generate_chart AI tool can render interactive Vega-Lite charts inline. (macOS Full is DuckDB-only: Homebrew qt@5 no longer ships QtWebEngine and there is no Apple-Silicon Qt5 WebEngine, so inline Vega charts are a Linux/Windows feature.) Everything else is identical. Most people want Lite; reach for Full only if you need the DuckDB engine or WebEngine-rendered Vega charts — the native QtCharts inline charts and the .npd diagram renderer work in both flavors on every platform. See Lite mode vs Full mode.
How big is it, really?
The bare executable is ~12 MB (~12.2 MB on Linux x64) on every platform — no Electron, no bundled browser runtime. Download sizes differ because Linux links Qt from your distro while macOS and Windows bundle it: roughly 4.4 MB (Linux x64 tar.gz), 27.7 MB (macOS DMG with Qt), 42.7 MB (Windows MSI with the Qt DLLs). The GitHub release page is always canonical for exact bytes.
Does my code go to the cloud? Is there any telemetry?
No telemetry, no analytics, no account — the editor starts fully offline. Every outbound connection is one you trigger: (1) your selected AI backend — a local Ollama (localhost:11434) or llama-server (localhost:8080) by default, or whichever URL you set on the llama.cpp entry; (2) git push/pull from the Git panel; (3) the REST client when you send a request; (4) one GitHub-API call at launch if the update check is enabled. Cloud AI backends (Ollama Cloud / OpenRouter / OpenAI / Azure OpenAI) are opt-in from the dropdown and use your key — your code leaves the machine only when you pick one and send it. All of this is verifiable with strace, and the built-in AI Interaction Log records exactly what was sent so you never have to take our word for it.
Do I need an API key or a subscription?
No. Point the AI dock at a local Ollama or llama.cpp model and it's free and offline forever — no key, no account, no usage cap beyond your own hardware. API keys only matter if you opt into a cloud backend, and then it's your key billed by that provider. Notepatra itself has no subscription, no paid tier, and takes no cut.
Where are my settings and API keys stored?
Everything lives in one config.json in your config directory — ~/.config/notepatra/ on Linux, %APPDATA%\Notepatra\ on Windows, ~/Library/Application Support/Notepatra/ on macOS. Be aware that API keys are written there in plaintext today — there's no encryption yet (OS-keychain integration is a planned improvement), so treat that file like any dotfile that holds secrets, and use a provider's Forget button to wipe a key on a shared machine.
Is the DuckDB "Data Analyst" included in the download?
Data Analyst mode ships and works out of the box on CSV files and an in-memory SQLite engine — load data, ask in plain English, get SQL and charts back. DuckDB now ships bundled in the prebuilt Full download (v1.1.3) on every platform. The Lite default download has CSV + in-memory SQLite only; pick a DuckDB connection there and it will honestly report "support not compiled in" — switch to the Full download to use DuckDB.
Will it open huge files?
Yes, within reason. Files up to ~1.86 GB load fully; above that they open truncated and read-only (use a streaming tool like less for the whole thing). Past 50 MB, Notepatra automatically turns off syntax highlighting, auto-completion, word wrap and indent guides to stay responsive — the file is still fully editable. The Rust core uses memory-mapped loading to avoid a double read on open.
Why GPL-3.0?
Because the source is open and we want modifications to stay open. Using Notepatra as an editor puts no obligation on the files you edit — the GPL governs Notepatra's own code, not your documents or projects (see the FSF GPL FAQ). If you're evaluating it for an organization, the For Enterprise page lays out the licensing posture, supply-chain provenance, and warranty position in plain English.
Will you add LSP support?
It's planned, not shipped — and we'd rather say that plainly than imply it already works. Today's autocomplete is QScintilla's word-based completion. The goal is to plug into language servers (clangd, rust-analyzer, pyright, …) for real completion and go-to-definition. It's tracked on the roadmap.
Where's the Windows ARM64 build?
Not yet. Current builds are Linux x64 / ARM64, macOS Apple Silicon, and Windows x64. Windows-on-ARM is a small but growing target and is tracked on the roadmap.
How do I report a bug or get help?
Open a GitHub issue — there are bug-report and feature-request templates. For anything security-sensitive, use GitHub's private vulnerability reporting (see the Security policy). Notepatra is free software with no SLA or support contract, but issues are read, and the release binary intentionally ships unstripped (with debug symbols) so crash reports come back with usable stack traces.
Contributing
See CONTRIBUTING.md for the full contributor guide. Short version:
- File issues via the issue templates (bug report, feature request)
- PRs should pass CI (build + tests on all 3 platforms) and include a test when fixing a bug
- Code style:
.clang-format(LLVM base, 4-space indent, 100 col) - Signed commits preferred
Security policy
See SECURITY.md and /.well-known/security.txt. Reports via GitHub private vulnerability reporting. 90-day disclosure window by default.
License
Notepatra is licensed under the GNU General Public License v3.0. No warranty. See GPL-3.0 §15 and §16 for the disclaimer of warranty and limitation of liability.