Notepatra Notepatra v0.1.114 docs

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.

What "0.1.x" means. Notepatra is built by a one-person team in the open and is not yet feature-complete relative to mature editors. The roadmap is deliberately public. Latest release is v0.1.114 (June 2026). See the FAQ for what's shipped vs. planned.

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.

PlatformAssetSize
🐧 Linux x64notepatra-linux-x64.tar.gz~4.4 MB
🐧 Linux ARM64notepatra-linux-arm64.tar.gz~4.1 MB
🍎 macOS Apple Siliconnotepatra-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
Linux: Qt5 required. The Linux tarball is just the bare binary — Qt5 is expected to be installed system-wide. On Ubuntu/Debian: 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.

🛡 Privacy guarantee. Notepatra never sends telemetry. Uninstalling removes only the binary, shortcuts, and your local config — nothing was ever phoned home, so there is nothing to revoke. No accounts, no API keys, no cloud state, no analytics. If you used the AI Assistant it connects to your local Ollama daemon; uninstalling Notepatra does not remove Ollama or any pulled models — manage those with the 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

🐧 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

🪟 Windows 10 · 11

If you installed via the NSIS installer (notepatra-setup-X.Y.Z.exe)

Easiest: use Windows Settings.

  1. Open Settings (Win+I)
  2. Apps → Installed apps
  3. Search for Notepatra
  4. Three-dot menu → Uninstall
  5. The NSIS uninstaller runs → Next → Uninstall

Alternative: run the uninstaller directly from %LOCALAPPDATA%\Notepatra\uninstall.exe.

The uninstaller automatically removes:

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

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.

FlavorBare binaryWhat you getWhat'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:

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 IDSizeWhat it doesStatus
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:

Path B — Download the Full flavor manually

On the GitHub Releases page pick the file with -full in the name:

Path C — Build from source with -DNOTEPATRA_WITH_WEBENGINE=ON

Works on any platform with QtWebEngine dev headers available:

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

UI overview

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

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:

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:

Find & replace

5-tab dialog: Find, Replace, Find in Files, Mark, Go to.

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

Query modes

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.

Tip: for a quick "is this string anywhere in my project?" use the default plain-text mode with the phrase typed as-is. Regex is only worth the syntax overhead when you actually need backtracking, alternation, or character classes.

Macros

Record keyboard + mouse operations and play them back:

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

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-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

  1. Pick a left and right file (open tab, unsaved tab, or file on disk).
  2. Rust's Myers diff (similar crate) produces a list of Equal / Insert / Delete entries.
  3. Consecutive Delete + Add blocks are paired into "modified" rows at the same visual line.
  4. 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 kindBackgroundSymbol marginCharacter highlight
Equal / contextwhite
Modified (paired)pale yellow #FFFBE6pink ~ (Circle)red box on left, green box on right — only differing chars
Added (right only)mint green #D4F4D4green + (Plus)
Deleted (left only)salmon #F4D4D4red − (Minus)
Placeholder (empty on one side)light blue #E8F0F8green + 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

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:

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, pwshcmd.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:

BackendTypeProtocol / URLWhat it gives you
Ollama (default)LocalNative /api/generate · http://localhost:11434Easiest 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 CloudCloudOpenAI-compat over HTTPS · https://ollama.comSame Ollama models, served from Ollama's hosted infrastructure. Per-provider key slot in Settings.
llama.cppLocalOpenAI /v1/chat/completions · http://localhost:8080Loads any GGUF file directly — no daemon, no config format. Maximum control + minimum overhead.
OpenRouterCloudOpenAI-compat · https://openrouter.ai/apiOne 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.
OpenAICloudOpenAI /v1/chat/completions · https://api.openai.comDirect OpenAI access for the GPT-4o / GPT-5 / o-series families. Per-provider key slot.
Azure OpenAICloudAzure 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:

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

  1. Install Ollamacurl -fsSL https://ollama.com/install.sh | sh (Linux/macOS) or download from ollama.com (Windows).
  2. Start the daemonollama serve. Listens on http://localhost:11434 by default.
  3. Pull at least one model. Recommended starter:
    • ollama pull qwen2.5:7b — 4.7 GB, general-purpose, good at code
    • ollama pull llama3.2:3b — 2 GB, smaller, faster
    • ollama pull codellama:7b — 3.8 GB, code-specialized
    • ollama pull qwen2.5-coder:7b — 4.4 GB, code-specialized + recent
  4. Launch Notepatra → open any AI panel → the model dropdown auto-populates with whatever you pulled.
Memory check. 7B models need ~6 GB RAM, 13B ≥ 10 GB, 34B ≥ 24 GB. For CPU-only / 16 GB laptops, Notepatra auto-picks the smallest installed model in this priority order: 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.

  1. Install llama.cppbrew install llama.cpp (macOS) or build from the repo (Linux / Windows).
  2. Download a GGUF model from huggingface.co. Try Qwen2.5-Coder-3B-Instruct-Q4_K_M.gguf (~2 GB, excellent for code).
  3. Run the serverllama-server -m path/to/model.gguf --port 8080. Exposes OpenAI-compatible endpoints at http://localhost:8080/v1/.
  4. 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

  1. Install — one-liner provided by Ollama:
    curl -fsSL https://ollama.com/install.sh | sh
    The installer drops a binary in /usr/local/bin/ollama and registers a systemd unit ollama.service.
  2. Daemon — the installer starts and enables it. Check status:
    systemctl status ollama
    journalctl -u ollama -f         # follow logs
    If your distro has no systemd (Void, Artix, Alpine, WSL1), run ollama serve in a terminal you keep open.
  3. Pull a model:
    ollama pull qwen2.5-coder:7b
  4. Verify:
    ollama list                     # should show the model
    curl http://localhost:11434/api/tags    # JSON list of installed models
  5. Notepatra config — open the AI dock, pick "Ollama" in the backend dropdown. The model dropdown auto-populates. No URL field to set; http://localhost:11434 is hard-wired.

🪟 Windows

  1. Install — download OllamaSetup.exe from ollama.com/download/windows and run it. Installs to %LOCALAPPDATA%\Programs\Ollama and starts a tray icon at boot.
  2. Daemon — the tray icon means it's running. Right-click the tray icon → "Quit Ollama" to stop. Re-launch from the Start menu.
  3. Pull a model — open PowerShell or cmd:
    ollama pull qwen2.5-coder:7b
  4. Verify:
    ollama list
    curl http://localhost:11434/api/tags
  5. Notepatra config — same as Linux: pick "Ollama" in the backend dropdown.

🍎 macOS

  1. Install — either the .dmg from ollama.com/download/mac, or via Homebrew:
    brew install --cask ollama
  2. Daemon — launching the Ollama app puts an icon in the menu bar and starts the server. Quit from the menu-bar icon to stop.
  3. Pull a model — open Terminal:
    ollama pull qwen2.5-coder:7b
  4. Verify:
    ollama list
    curl http://localhost:11434/api/tags
  5. 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:

Models don't appear in Notepatra dropdown

Ollama is reachable (banner is green) but the dropdown is empty or stale.

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:

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.

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

  1. Clone and build:
    git 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 -j
    Binaries land in build/bin/. Add to PATH or copy llama-server somewhere in your $PATH.
  2. Verify:
    llama-server --version

🪟 Windows — Releases zip

  1. Download the latest pre-built zip from github.com/ggml-org/llama.cpp/releases. Pick llama-bXXXX-bin-win-cuda-x64.zip if you have an NVIDIA GPU, or ...-vulkan-... for AMD/Intel, or ...-avx2-... for CPU-only.
  2. Extract to a folder you'll remember (e.g. C:\llama.cpp) and add it to your PATH environment variable, or always invoke with the full path.
  3. Verify in PowerShell:
    llama-server.exe --version

🍎 macOS — Homebrew

  1. Install:
    brew install llama.cpp
    Apple Silicon Macs get Metal acceleration by default — no extra flags needed.
  2. 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.

QuantSize (7B)QualityWhen to pick
Q4_K_M~4.4 GBGoodDefault. Fits on 8 GB RAM / 6 GB VRAM. Recommended.
Q5_K_M~5.1 GBBetterNoticeably sharper on coding. Needs ~10 GB free.
Q8_0~7.7 GBNear-losslessIf you have 16 GB+ and want max fidelity short of full precision.
F16 / BF16~14 GBLosslessResearch / 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:

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:

Curated catalog showing instead of my loaded model

The dropdown lists Notepatra's curated catalog rather than the model you loaded.

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)

  1. Sign up at openrouter.ai. Add a few dollars credit; pay-as-you-go per token, no subscription.
  2. Create a key — Account → Keys → Create. Copy the sk-or-v1-... string.
  3. Paste in Notepatra — Settings → AI → OpenRouter section → API Key field → click Test. Green = good. Click Save.
  4. 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

  1. Get a key at platform.openai.com/api-keys. The string starts with sk- (or sk-proj- for project keys).
  2. Paste in Settings → AI → OpenAI section → Test → Save.
  3. Pick "OpenAI" in the backend dropdown. Curated list of the GPT-4o / GPT-5 / o-series families; type gpt-5 or o4 to 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.

  1. 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.
  2. 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.
  3. 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.

  1. Sign up at ollama.com and create an API key in your account settings.
  2. Settings → AI → Ollama Cloud — paste the key → Test → Save.
  3. Pick "Ollama Cloud" in the backend dropdown. The model list is the cloud catalog.

Per-provider key management

Every key slot has three buttons:

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:

Troubleshooting

"Key invalid" — but it works in curl

Test button reports failure even though the same key works from a terminal.

Rate-limit errors / 429

Provider replies with HTTP 429.

Model not in dropdown after refresh

You expect a specific model and it's not in the list, even after clicking refresh.

Cross-cutting troubleshooting

Backend-agnostic problems and their fixes.

AI panel says "thinking…" forever
Stop button doesn't stop
Coding mode sends but no tool calls fire
Capabilities probe never returns
Where Notepatra stores AI config

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:

  1. Strip <think>...</think> blocks — defensive regex strip for models that emit reasoning despite think: false.
  2. Strip markdown ``` fences — if the response starts with ```, find the first newline and the last fence and keep the middle.
  3. Trim leading prose — find the first { or [ in the response and discard everything before. Handles "Here is the fixed JSON: {...}".
  4. 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:

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:

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:

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:

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:

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:

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:

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:

ToolWhat 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_showRead-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:

  1. 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/, ~/.netrc and the like — they fall outside the workspace anchor (error_kind: outside_workspace), not via the deny-list below. Also catches symlink-to-secrets attacks.
  2. 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).
  3. 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:

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:

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

The two new agentic tools

ToolWhat 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+):

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:

SQL Server — connecting to an existing server (Windows / macOS / Linux)

  1. In Manage Connections, pick the SQL Server (localhost, ODBC) preset to pre-fill the form.
  2. Change Host to your server's address. For named instances (e.g. SQL Express): SERVER\INSTANCE and set Port to default.
  3. For SQL Authentication: enter your SQL login + password.
  4. For Windows Authentication (domain account / current Windows user, Windows only): clear Username, leave Password empty, and add ;Trusted_Connection=yes to Options.
  5. For TLS-required servers (Azure, modern on-prem): change Options to DRIVER={ODBC Driver 18 for SQL Server};Encrypt=yes;TrustServerCertificate=no.
  6. 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)

  1. Pick the PostgreSQL (localhost) preset.
  2. For a local Postgres, leave everything at the defaults and enter your password.
  3. 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 accept postgres as default).
  4. For TLS-required servers (any managed PG should require TLS), set Options to sslmode=require (or sslmode=verify-full;sslrootcert=/path/to/ca.pem for cert pinning).
  5. Unix-socket connections (lower latency on the same host): leave Host empty, set Options to host=/var/run/postgresql.

MySQL / MariaDB

  1. Pick the MySQL / MariaDB (localhost) preset.
  2. For local servers, defaults are fine — set your password and the database name.
  3. For RDS / PlanetScale / managed MySQL, set Options to SSL_CA=/etc/ssl/certs/ca-certificates.crt;MYSQL_OPT_CONNECT_TIMEOUT=10.
  4. For Unix-socket: clear Host, add UNIX_SOCKET=/var/run/mysqld/mysqld.sock to Options.

SQLite — file-based

  1. Pick the SQLite (file on disk) preset — focus jumps to Database.
  2. Click Browse… and pick the .db / .sqlite / .sqlite3 file (or type a path — the file is created if it doesn't exist).
  3. 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.

  1. Pick the DuckDB (file or :memory:) preset — Database defaults to :memory:.
  2. 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 with region;access_key_id;secret;session_token
  3. No host / port / username / password — DuckDB runs in-process via the native libduckdb engine.

Driver availability per OS

DriverLinux (Debian/Ubuntu)macOS (Homebrew)Windows
QSQLITEBuilt into Qt — always availableBuilt into Qt — always availableBuilt into Qt — always available
QPSQL (PostgreSQL)sudo apt-get install libqt5sql5-psqlbundled in brew install qt@5Bundled with the Notepatra Windows release
QMYSQL (MySQL/MariaDB)sudo apt-get install libqt5sql5-mysqlbundled in brew install qt@5Bundled 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 unixodbcBundled with the Notepatra Windows release (Microsoft ships ODBC drivers with Windows itself)
DUCKDBBundled 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

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:

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:

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)

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:

  1. Passes think: false in the /api/generate request body (honored by modern Ollama)
  2. Appends /no_think to the system prompt (honored by some models as a slash-command)
  3. 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 kindHandled 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.
📕 PDFpdftotext -layout via QProcess (requires poppler-utils), extracted text appended to the prompt as context, capped at 100 KB.
📘 DOCX / ODTunzip -p file.docx word/document.xml, XML tags stripped, appended to prompt.
📙 PPTXunzip -p file.pptx ppt/slides/slide1.xml, XML stripped, appended (first slide only for now).
📗 XLSXunzip -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 elseAttempted 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…

🛡 Privacy by design. The log lives entirely on your machine — there is zero network egress. Before anything is written, a credential scrubber masks API keys, bearer tokens, and PEM private keys. Entries auto-prune after 7 days. The feature is on by default with a one-click opt-out in Settings.

What the viewer gives you

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

  1. 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.
  2. New — start from a Flow, ER or System template and tweak it.
  3. Write .npd in 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 shapenode 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+NNew
Ctrl+OOpen
Ctrl+SSave
Ctrl+Shift+SSave As
Ctrl+Alt+SSave All
Ctrl+WClose tab
Ctrl+PPrint

Edit

Ctrl+ZUndo
Ctrl+Y / Ctrl+Shift+ZRedo
Ctrl+X / Ctrl+C / Ctrl+VCut / Copy / Paste
Ctrl+ASelect all
Ctrl+DDuplicate line
Ctrl+Shift+KDelete line
Ctrl+/Toggle line comment
Ctrl+Shift+UUPPERCASE selection
Ctrl+Ulowercase selection
Ctrl+Shift+↑ / Ctrl+Shift+↓Move line up / down

Search

Ctrl+FFind
Ctrl+HReplace
F3 / Shift+F3Find next / previous
Ctrl+GGo to line
Ctrl+BGo to matching brace (swivels between open/close)
Ctrl+F2Toggle bookmark
F2Next bookmark
Shift+F2Previous bookmark

View / Navigation

Ctrl+= / Ctrl+-Zoom in / out
Ctrl+0Reset zoom
Ctrl+TabNext tab
Ctrl+Shift+TabPrevious tab
Ctrl+Shift+EToggle File Explorer sidebar
Ctrl+Shift+AToggle AI Assistant dock
Ctrl+Shift+GOpen Project Search
F11Full screen

Macro

Ctrl+Shift+MStart macro recording
Ctrl+Shift+TStop macro recording
Ctrl+Shift+PPlay 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:

OSPath
Linux~/.config/notepatra/ (honours $XDG_CONFIG_HOME)
macOS~/Library/Application Support/Notepatra/
Windows%APPDATA%\Notepatra\ (Roaming)

Files inside that directory

Build from source

Dependencies

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

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

  1. Check the Ollama Status bar at the top of the JSON Tools panel — is the dot green?
  2. If red: ollama serve in a terminal, check port 11434.
  3. If green but no response: make sure you've pulled at least one model: ollama list.
  4. 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:

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.