VispNote is a local-first desktop note app for individual knowledge workers who want to write, connect, and act without configuring a productivity system first.
The default experience stays deliberately small: Notes, Today, Pinned, Tags, fast capture, search, and note-level connections. Your notes remain usable as plain files even if you stop using the app.
attachments/.The core loop is intentionally simple:
Specialist capabilities live in optional packs so they do not become setup work:
| Pack | Purpose |
|---|---|
| Planning | Agenda and workflow views when dated tasks or workflow data exist. |
| Thinking Board | Arrange notes, stickies, and connections spatially. |
| Research | Zotero-assisted source reading and synthesis. |
| Writer | Long-form structure, scenes, and novelist-compatible vault metadata. |
| Agents | MCP and local llm-memory integration. |
| Labs | Global graph, Smart Views, and experimental specialist tools. |
Activation never changes note content. Existing canvases, novelist vaults, Zotero configuration, and memory configuration are detected automatically. Ask AI is optional and appears only after assistance is enabled.
VispNote can also keep a private, allowlisted feature-usage report on the device. It contains aggregate counters and repeat-use days—including first-note completion, successful capture, search-result opening, and Today actions—never note text, titles, tags, searches, prompts, filenames, paths, vault IDs, or secrets. The report can be previewed, exported, cleared, or disabled. Anonymous aggregate sharing is separately opt-in and appears only in builds configured with VISPNOTE_TELEMETRY_ENDPOINT.
better-sqlite3sqlite-vec for vector indexing supportnode:test for fast editor operation testsInstall dependencies:
npm install
Start the app:
npm start
Run the main checks:
npm run test:editor
npm run check:main
npm run regression:renderer
npm run benchmark:10k
The 10,000-note benchmark uses an isolated temporary vault and enforces a 100 ms p95 budget for direct result projection plus a one-second p95 budget for indexed search. See Final hardening for the compatibility, privacy, accessibility, and packaging gates.
Run the Electron smoke test:
npm run smoke:electron
npm run regression:renderer
.
├── vispnote.html # Electron renderer entry point
├── main.js # Electron main process and IPC handlers
├── preload.js # Safe renderer bridge
├── lib/
│ ├── store.js # Filesystem vault storage
│ ├── index.js # SQLite search/backlink/tag index
│ ├── ai.js # Local AI orchestration
│ ├── ollama.js # Ollama client helpers
│ └── seed.js # First-run seed vaults
├── src/
│ ├── main.jsx # Renderer bootstrap and import order
│ ├── app/ # App shell, mutations, canvas actions, App API registry
│ ├── ai/ # Ask AI UI and AI action planning helpers
│ ├── editor/ # Note editor, outliner, markdown model, editor operations
│ ├── panels/ # Sidebar, note list, graph, agenda, today, workflow panels
│ ├── canvas/ # Canvas dashboard view
│ ├── settings/ # Settings modal
│ └── shared/ # Theme, markdown rendering, plugins, storage utilities
├── tests/
│ └── editor-ops.test.js # Regression tests for editor behavior
└── scripts/
└── smoke-electron.js # Electron startup smoke test
New installs store vault data in:
~/VispNote
Existing data under ~/OminiNote or ~/MyNote is still supported as a compatibility fallback when ~/VispNote does not exist.
The repository intentionally ignores local vault data, SQLite databases, generated build output, local tool state, and environment files. Do not commit personal notes, local indexes, .env files, or generated app packages.
VispNote ships a local MCP (Model Context Protocol) server so AI agents such as Claude Code can use your vaults as a knowledge base — entirely on your machine, with no cloud sync.
node bin/vispnote-mcp.js # read-only (default)
node bin/vispnote-mcp.js --allow-writes # also enables create_note / append_to_note
Example Claude Code configuration (.mcp.json):
{
"mcpServers": {
"vispnote": {
"command": "node",
"args": ["/path/to/visp-note/bin/vispnote-mcp.js"]
}
}
}
Tools: list_vaults, search_notes, get_note, get_backlinks,
get_unlinked_mentions, list_notes_by_tag, and (only with
--allow-writes) create_note and append_to_note. The server reads the
same vaults and SQLite index as the app (safe to run alongside it), is
read-only by default, and never listens on the network — it speaks MCP over
stdio to the process that launched it.
Note on concurrent edits: if an agent appends to a note that is open with unsaved changes in the app, the app’s next autosave detects the conflict and asks which version to keep — choosing “keep mine” discards the agent’s append. Prefer agent writes to notes you are not actively editing.
VispNote can pair with a local llm-memory server so your notes and your agents share one memory:
llm-memory serve).#memory with provenance properties
(memoryId::, memoryLayer::, …). Imported notes are yours — re-imports
never overwrite them.npm run regression:memory exercises the whole bridge against a real
llm-memory server (for example the Docker container): create → recall →
import-as-note → remember → cleanup, all inside an isolated
vispnote_regression repo id. If no server is reachable the run is skipped,
so it remains an optional local integration check. npm run test:all runs the
self-contained release gates; npm run test:all:with-memory adds the optional
live regression. Set VISPNOTE_MEMORY_REQUIRED=1 to make an unreachable server
a failure and use VISPNOTE_MEMORY_URL / VISPNOTE_MEMORY_API_KEY for a
loopback service with non-default settings.
AI features are optional and disabled until enabled in Settings > Assistance.
Typical flow:
gemma3.nomic-embed-text.If Ollama is not available, the core note app still works.
npm run test:editor covers the high-risk editor behaviors, including:
npm run check:main syntax-checks the Electron main/preload and backend modules.
Before publishing a release:
npm run test:allVISPNOTE_MEMORY_REQUIRED=1 npm run regression:memory against a
provisioned local llm-memory servicenpm run benchmark:10k--x64 or --arm64);
the builder configuration intentionally has no fallback architecture listnpm run verify:package-renderer -- --platform <platform> --arch <arch>
and stage/verify final installers under dist/release-output before uploading0.2.2
must use tag v0.2.2.gitignore is not allowing local vault data or database filesgit status --ignored if local tool or generated files are presentThe release workflow uploads a fixed, per-matrix inventory into separate
artifact directories and refuses missing, extra, empty, duplicate, corrupt, or
wrong-CPU packages. macOS publishing additionally requires MAC_CSC_LINK,
MAC_CSC_KEY_PASSWORD, APPLE_API_KEY_BASE64, APPLE_API_KEY_ID, and
APPLE_API_ISSUER; signing, Gatekeeper assessment, and notarization ticket
validation all fail closed. Set the VISPNOTE_MEMORY_IMAGE repository variable
to a pinned llm-memory service image before publishing; an optional
VISPNOTE_MEMORY_API_KEY secret is passed to secured images. macOS updates
remain manual, so macOS updater metadata is intentionally not published.
The desktop app is free.
VispNote is licensed under the Apache License 2.0. See LICENSE.