dingovault

command module
v1.4.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 13, 2026 License: AGPL-3.0 Imports: 27 Imported by: 0

README

Dingovault

中文文档 | English

Release Test Go Report Card Go mod License Stars Forks

High-performance, local-first outliner with SaaS sync, built in Go.

From source (CLI / server binary):

go install github.com/cndingbo2030/dingovault/cmd/dingovault@latest

Go module path: github.com/cndingbo2030/dingovault

Dingovault is a block-based Markdown vault: fast full-text search (FTS5), wikilinks, YAML frontmatter, and a clean desktop shell. The same core runs offline against embedded SQLite or online against your self-hosted or managed SaaS API—switchable via a small storage.Provider abstraction.

Why Dingovault?

Speed that feels like zero latency. Dingovault is built for people who live in their notes. Full-text search over your vault is tuned until it is effectively instant—warm local runs are commonly around ~1ms median for FTS queries and sub‑millisecond page loads on typical hardware (always measure yours with make benchmark). No spinners for “finding that one bullet.”

Military‑grade privacy for your words. Your vault can sit behind AES‑256‑GCM encryption at rest (DINGO_MASTER_KEY), so disk theft does not mean plaintext theft. Pair that with JWT‑protected SaaS APIs when you self‑host the server, and you keep multi‑user deployments on a short leash.

AI without shipping your brain to the cloud. Dingovault talks to Ollama and other local endpoints first: inline assist, vault‑aware chat, and optional embeddings stay on your machine when you want them to—so “RAG over my notes” does not have to mean “send every block to someone else’s GPU.”


v1.4.2 — AGPL-3.0, GHCR image & npm SDK stub

Details: CHANGELOG.md.

  • License: AGPL-3.0; GHCR ships ghcr.io/cndingbo2030/dingovault on each tag; @cndingbo2030/dingovault-sdk on GitHub Packages.

v1.4.1 — Workflow fixes & semantic release filenames

Details: CHANGELOG.md.

  • Android CI: stable NDK / SDK env (ANDROID_HOME, NDK_HOME, ndk-bundle symlink) and gomobile init ordering.
  • Release assets: descriptive names (macOS-Apple-Silicon-M1-M2-M3, macOS-Intel-Processor, Windows-64bit-Installer, Linux-Desktop-amd64, Android-Universal-Install, etc.).
  • UI: safe-area + dynamic header for tablet landscape vs phone.

v1.4.0 — Android gomobile library & responsive UI

Details: CHANGELOG.md.

  • gomobile .aar under cmd/dingovault-android/mobile plus a minimal Gradle shell for CI-built APK / AAB artifacts on version tags.
  • Scoped storage helper (AndroidScopedVaultPath) for vault roots under getExternalFilesDir/app-specific external storage.
  • Responsive UI: dynamic viewport height, 48px touch targets, bottom tab bar on phones, three-column outline / semantic / backlinks layout from 900px width up.

v1.3.2 — WebDAV, S3-compatible sync & LAN discovery

Details: CHANGELOG.md.

  • WebDAV two-way sync for .md files with timestamp + size rules; divergent edits become *.conflict.md siblings.
  • S3-compatible object storage sync with the same conflict rules (AWS S3, MinIO, and other API-compatible hosts).
  • mDNS LAN discovery plus 4-digit PIN pairing to copy sync settings between machines on the same Wi‑Fi (bridge API + bindings; wire your own Sync Settings UI or call the Wails methods).

Full user-facing notes: see CHANGELOG.md.

  • Real-time inline AI: streaming text as the model writes, with graceful recovery if the AI server disconnects.
  • Vault-aware chat: answers combine the open page with semantically related blocks from your notes (optional embeddings; local-first).
  • Semantic related & graph: discover similar blocks and optional meaning-based links alongside wikilinks.
  • Smarter tag suggestions based on how each block reads.

v1.2.0 Master Release

  • New premium visual identity with refreshed app branding and icon pipeline.
  • 100% clean-code push: complex paths refactored for better maintainability.
  • Enhanced macOS Gatekeeper guidance for unsigned app bundles.
Why teams pick Dingovault (technical checklist)
  • Benchmarks, not vibes: run make benchmark for FTS p50 / page-load p50 on your disk (see Why Dingovault? above for typical ballparks).
  • Encryption & SaaS hardening: DINGO_MASTER_KEY (AES‑256‑GCM at rest) and JWT‑gated HTTP APIs for multi‑tenant or team installs.
  • Plugin-ready architecture: backend hooks (before:block:save, after:block:indexed) and frontend plugin slots make it easy to extend without forking core logic.

Maintainer & contact

Maintainer cndingbo2030
Email cndingbo@outlook.com
Repository github.com/cndingbo2030/dingovault

Stack

Layer Technology
Runtime Go (see go.mod for the exact toolchain)
Desktop Wails v2 + webview
UI Svelte + Vite
Local index SQLite + FTS5 (modernc.org/sqlite)
Markdown Goldmark
SaaS API net/http, JWT (HS256), REST under /api/v1

Architecture

storage.Provider

All graph and UI persistence go through storage.Provider (internal/storage/provider.go):

  • Store (internal/storage/sqlite.go) — local SQLite + triggers keeping FTS in sync.
  • RemoteStore (internal/storage/remote.go) — HTTP client: Authorization: Bearer <JWT> on every call, mapping to the same REST routes the SaaS server exposes.

The graph service (internal/graph) and Wails bridge (internal/bridge) depend only on Provider, not on SQL or HTTP—so the desktop app can run in local or cloud mode without forking business logic.

SaaS server

cmd/dingovault can run an HTTP server on DINGO_PORT (default 12030), with routes registered in internal/server/handlers.go. Protected handlers read the tenant from the JWT (sub) and scope SQLite rows by user_id.


Performance

  • Local FTS: prefix-token queries over FTS5 are typically around ~1ms p50 on modest vaults after warmup.
  • Page load: serving one page’s block tree from SQLite is typically around ~0.2ms p50 of database work on warm local cache.

Exact numbers depend on hardware, vault size, and OS cache—run make benchmark on your machine for a reproducible report.

Encrypted stress + integrity: make benchmark-encrypted sets DINGO_MASTER_KEY and runs the benchmark with -verify so decrypted block content is spot-checked after indexing.


Schema migrations & plugins (v1.0+)

  • First launch: If you start the desktop app with no -notes flag and no saved vaultPath, Dingovault unpacks the embedded demo-vault/ into your OS cache and opens it so you can try the outliner immediately. Set DINGO_NO_DEMO_VAULT=1 to disable that behavior.
  • SQLite user_version: On open, internal/storage/migrate.go runs incremental migrations so upgrades can add tables/columns without wiping existing notes. Bump CurrentSchemaVersion and add a new step when the schema changes.
  • before:block:save: Register on the graph service’s bus with RegisterBeforeBlockSave to mutate markdown before it is written (e.g. auto-formatting, AI hooks). Errors abort the save.
  • after:block:indexed: Pub/sub topic after:block:indexed fires after a source is reindexed (alongside the existing file reindex topic).
  • Reference AI plugin: internal/plugins/summarizer subscribes to after:block:indexed; when a block includes #summarize, it appends a generated child summary and reindexes through storage.Provider.
  • Desktop UI: External scripts can call window.__DINGOVAULT__.registerToolbarButton / registerSidebarSection (see frontend/src/pluginRegistry.js). Missing images get a placeholder via initImageFallback().

Production hardening (SaaS)

Variable Purpose
DINGO_ENV=production Enables strict JWT rules: DINGO_JWT_SECRET is required and must not be the built-in development default. The Docker image sets this by default.
DINGO_JWT_SECRET HS256 signing key (minimum 16 characters). Generate a long random string for production.
ALLOWED_ORIGINS Optional comma-separated exact browser origins allowed for CORS (e.g. https://app.example.com,http://localhost:5173). If unset, no Access-Control-Allow-Origin is sent (non-browser / same-origin clients unaffected).
DINGO_MASTER_KEY Optional passphrase: AES-256-GCM encryption for block content in SQLite (dv1: prefix). FTS body search is ineffective on ciphertext. Losing or changing the key makes encrypted rows unreadable.
DINGO_BLOB_BACKEND filesystem (default) or s3 / minio for POST /api/v1/assets.
S3 / MinIO DINGO_S3_BUCKET, DINGO_S3_REGION (default us-east-1), optional DINGO_S3_ENDPOINT, DINGO_S3_PREFIX, DINGO_S3_PUBLIC_BASE (no trailing slash; markdown links), DINGO_S3_USE_PATH_STYLE=1. Auth: AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY or DINGO_S3_ACCESS_KEY / DINGO_S3_SECRET_KEY.
Health & metrics
Endpoint Auth Description
GET /api/v1/health Public Liveness JSON {"status":"ok"}.
GET /api/v1/sys/stats JWT Global index stats: blockCount, pageCount, tenantCount (distinct user_id in blocks; tenants with no blocks are not counted).
POST /api/v1/capture JWT Quick capture: JSON {"text":"…","sourcePath":"Inbox.md"} (default path Inbox.md). Appends a bullet under the vault page and reindexes. Requires -notes / vault path on the server.
POST /api/v1/assets JWT Multipart field file. Filesystem mode: vault/assets/ (needs vault path). S3 mode: DINGO_BLOB_BACKEND=s3 + bucket env (no local vault required for uploads). Returns path, markdown, bytes.
GET /api/v1/graph/wiki JWT Page-level graph: nodes (id = absolute path, label) and edges (sourcetarget) from resolved wikilinks. Requires vault path for alias resolution.
Mobile / automation
  • Siri Shortcuts / widgets: POST /api/v1/capture with a Bearer token is enough to append to an inbox page without loading the block tree.
  • CORS: set ALLOWED_ORIGINS so browser-based or extension clients can call the API from your SPA origin.
Desktop UX (Phase 14)
  • Fold: parent blocks can be collapsed; state is stored in localStorage per page (dingovault-collapse:<path>), so large outlines stay manageable without changing Markdown yet.
  • Drag ⋮⋮: reorder sibling blocks (same parent) via the Wails binding ReorderBlockBefore (file-backed, same rules as indent/outdent).
  • Graph button: force-directed page link graph (resolved wikilinks) using d3-force.
Mobile & privacy (Phase 15)
  • Responsive UI: touch-sized controls, 16px textarea font (reduces iOS zoom), safe-area padding, stacked toolbar on narrow screens.
  • Swipe on the left rail: left = cycle TODO (same as desktop shortcut); right = clear block text (confirm). Gestures use the gutter so vertical scrolling in the editor stays natural.
  • Cloud assets: enable DINGO_BLOB_BACKEND=s3 to store uploads in S3-compatible storage; markdown uses DINGO_S3_PUBLIC_BASE URLs.
  • Releases: push a tag v1.2.3 to run .github/workflows/release.yml (Go tests, dingovault-server-* CLI matrix, Wails builds for Linux / macOS / Windows). Adjust runner packages if a platform fails in your fork.

Usage

Prerequisites
  • Go (matching go.mod)
  • Node.js + npm (for the frontend)
  • Wails CLI v2 for desktop builds
Desktop (local SQLite)
make dev
# or
wails dev

Point -notes at your vault directory (saved in user config after first run).

Desktop (cloud / SaaS index)
  1. Run a SaaS server (see below) and obtain a JWT, e.g.
    POST /api/v1/auth/token with {"userId":"your-id"} (dev-style; replace with real auth in production).

  2. Enable cloud mode via config (~/.config/dingovault/config.json on Linux):

    {
      "vaultPath": "/path/to/your/markdown/vault",
      "cloudMode": true,
      "cloudApiUrl": "http://127.0.0.1:12030",
      "cloudToken": "<paste JWT here>"
    }
    

    Or use environment variables (override config):

    • DINGO_CLOUD_MODE=1
    • DINGO_CLOUD_URL=http://127.0.0.1:12030
    • DINGO_CLOUD_TOKEN=<jwt>
  3. Start the desktop app as usual (wails dev / wails build). The vault folder remains the source of truth on disk; indexing pushes parsed content to the API on full scan, watcher events, and edits.

SaaS API server (CLI)

Development (default dev JWT secret allowed):

DINGO_SERVER=1 go run ./cmd/dingovault -db=./dingovault_saas.db

Production (strict secret):

export DINGO_ENV=production
export DINGO_JWT_SECRET='your-unique-secret-at-least-16-chars'
export ALLOWED_ORIGINS='https://your-spa.example.com'
DINGO_PORT=12030 go run ./cmd/dingovault -server -db=./dingovault_saas.db

Or only set DINGO_PORT (also enables HTTP):

DINGO_PORT=12030 go run ./cmd/dingovault -server -db=./dingovault_saas.db
Docker (SaaS image)

The image sets DINGO_ENV=production; you must pass a real JWT secret at run time:

make deploy-saas
docker run --rm -p 12030:12030 \
  -e DINGO_JWT_SECRET='your-unique-secret-at-least-16-chars' \
  -e ALLOWED_ORIGINS='https://app.example.com' \
  -v dingovault-data:/data \
  dingovault-saas:latest

Health: GET http://localhost:12030/api/v1/health
Stats (JWT): GET http://localhost:12030/api/v1/sys/stats

For /api/v1/capture, /api/v1/assets, and /api/v1/graph/wiki, run the binary with -notes / a mounted vault directory (same as non-Docker SaaS). The stock Docker example is API-oriented; mount your Markdown tree and pass -notes=/vault (or extend the image entrypoint) if you need those routes.


macOS installation (Gatekeeper)

If macOS shows a malware/untrusted developer warning for the downloaded app:

  1. Right-click Dingovault.app and choose Open (then confirm).
  2. If needed, clear quarantine metadata manually:
xattr -cr /Applications/Dingovault.app

This is expected for unsigned open-source app bundles.


Makefile targets

Target Purpose
make dev Wails dev (desktop)
make build / make release Production Wails build
make benchmark Index + FTS stress benchmark
make benchmark-encrypted Same with DINGO_MASTER_KEY + -verify (integrity spot-check)
make fmt go fmt ./...
make lint-frontend Svelte / TS checks
make dist Zip app bundle + help vault
make deploy-saas Build dingovault-saas:latest Docker image
Git tag v* Triggers release workflow: tests, cross-platform server binaries, Wails desktop artifacts (see .github/workflows/release.yml).

API overview (v1)

Public: GET /api/v1/health, POST /api/v1/auth/token

Protected (Authorization: Bearer …): blocks, pages, search, backlinks, alias resolve, POST /api/v1/pages/reindex, GET /api/v1/sys/stats, POST /api/v1/capture, POST /api/v1/assets, GET /api/v1/graph/wiki, etc. See internal/server/handlers.go and internal/server/phase14_handlers.go.


Repository metadata

Upstream: github.com/cndingbo2030/dingovault
Also see project.meta.json.


Container image (GitHub Container Registry)

On each v* tag, CI builds and pushes the SaaS server image:

docker pull ghcr.io/cndingbo2030/dingovault:v1.4.2
docker run --rm -p 12030:12030 -e DINGO_JWT_SECRET='your-secret-at-least-16-chars' -v dingovault-data:/data ghcr.io/cndingbo2030/dingovault:latest

Image labels include org.opencontainers.image.source and AGPL-3.0. See Dockerfile.

Plugin SDK stub (GitHub Packages / npm)

The scoped package @cndingbo2030/dingovault-sdk is published from sdk/ on each release tag (stub today; reserves the name for future typed APIs). Install instructions: sdk/README.md.

License

This project is licensed under the GNU Affero General Public License v3.0 — see LICENSE. If you run a networked modified version, AGPL requires you to offer corresponding source to users interacting with it over a network.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
cmd
dingovault command
dingovault-android/mobile
Package mobile is built with gomobile bind for Android (.aar).
Package mobile is built with gomobile bind for Android (.aar).
internal
ai
bus
domain
Package domain defines core Dingovault data models shared across layers.
Package domain defines core Dingovault data models shared across layers.
network
Package network provides LAN discovery (mDNS) and PIN-based credential exchange for sync setup.
Package network provides LAN discovery (mDNS) and PIN-based credential exchange for sync setup.
onboarding
Package onboarding provisions first-run demo content for new users.
Package onboarding provisions first-run demo content for new users.
sync
Package vaultsync mirrors Markdown vaults to WebDAV and S3 remotes using timestamp + size rules.
Package vaultsync mirrors Markdown vaults to WebDAV and S3 remotes using timestamp + size rules.
tenant
Package tenant carries per-request tenant/user identity through context.
Package tenant carries per-request tenant/user identity through context.
version
Package version holds the application version string embedded at link time for desktop builds.
Package version holds the application version string embedded at link time for desktop builds.
Command: go run ./scripts/benchmark.go [-dir DIR] [-files 50] [-total 10000] Generates randomized markdown, indexes into a temp SQLite DB, and reports FTS + GetPage latency.
Command: go run ./scripts/benchmark.go [-dir DIR] [-files 50] [-total 10000] Generates randomized markdown, indexes into a temp SQLite DB, and reports FTS + GetPage latency.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL