Synapse User Guide¶
Version: v2.1.0 Language toggle: English / Italian available in Settings.
2.1.0 note: The native iOS app was rebuilt from the ground up (§17) — a new 5-tab shell (Home · Wiki · Chat · Graph · More) and a brand-matched design system, replacing the prior Wiki-first layout. No API or deploy changes since 2.0.0.
2.0.0 note: The JSON ingest pipeline ("json" mode) has been removed. Ingest always uses the block-based engine. API error responses now use the stable envelope
{"error": {"code": "...", "message": "...", "status": N, "details": null}}— if you have scripts that parsed{"detail": "..."}, update them to readerror.messageinstead.
1. What is Synapse?¶
Synapse is a self-hosted web service that turns a folder of raw documents into a
self-organizing knowledge wiki. Drop a file into vault/raw/sources/, and Synapse
analyzes it with a configurable AI provider, creates structured wiki pages in
vault/wiki/, links them to related concepts, and lays out the whole knowledge graph
for you to explore.
The design follows the Karpathy LLM Wiki pattern: the AI maintains the wiki, and you curate it. The human curates; the LLM maintains. At no point does the AI apply a change to your wiki without either your explicit approval (lint, review queue) or the triggering of an explicit ingest action you initiated.
The vault model¶
Synapse manages three layers inside a single vault/ directory:
| Layer | Location | Who writes it |
|---|---|---|
| Raw sources | vault/raw/sources/ |
You — drop files here; Synapse never touches the originals |
| Wiki pages | vault/wiki/ |
Synapse generates; you can edit directly |
| Rules and purpose | vault/schema.md + vault/purpose.md |
You set the goal and rules; Synapse respects them |
The wiki/ folder is a valid Obsidian vault. Generated pages use compact YAML frontmatter
(type, title, created, updated, optional tags/related; corpus pages also carry the
reserved synapse_generation_key). Source provenance remains indexed in Postgres. Pages use
[[wikilinks]] and an
auto-generated .obsidian/ configuration. You can open vault/wiki/ directly in
the Obsidian app without any conversion or export step.
What Synapse does not do¶
- It does not modify
vault/raw/sources/— raw files are immutable. - It does not re-scan the entire vault on every change (I1: only the affected files are re-indexed).
- It does not run a force-directed layout on the browser — graph layout is computed server-side and cached (I2).
- It does not re-render on every streaming token — Markdown and LaTeX are parsed at the end of a stream (I3).
2. Quick start — the core journey¶
- Open the app — you land on the Home dashboard. Glance at the KPI row and domain section cards.
- Drop a document into
vault/raw/sources/(or use the upload zone in Sources), or drag a file onto the upload zone in the browser. - Watch the graph grow — the knowledge graph updates automatically once the AI finishes generating wiki pages.
- Inspect a page — click any node in the Graph section, or any row in the Wiki tree, to read its content and metadata.
- Chat with your wiki — ask questions in the Chat section; answers stream token by token with inline citations you can click.
- Act on proposals — visit the Review section to see what the AI thinks is worth following up on; choose Create, Deep Research, or Skip per item.
- Configure your provider — in Settings, open "AI & provider" to add, change, or remove an inference provider.
3. The interface¶
Synapse uses a dark-themed shell with a labeled navigation rail on the left side.
Navigation rail¶
The leftmost strip is approximately 72 px wide. Each item shows an icon and a persistent text label below it. The active section is highlighted with a rounded rectangle. The rail never hides labels on desktop — on screens narrower than 768 px the labels are hidden and only icons are shown.
The rail is split into two tiers:
Top tier — places:
| Label | Section | Description |
|---|---|---|
| Home | Home dashboard | Vault KPIs, recent activity, domain section cards |
| Chat | Chat | Multi-conversation streaming chat with retrieval |
| Wiki | Wiki | Three-panel page browser, editor, and inspector |
| Sources | Sources | Raw source file browser + upload zone |
| Search | Search | Full-text and semantic search across wiki pages |
| Graph | Graph | Full-bleed sigma.js knowledge graph |
Middle tier — tools:
| Label | Section | Description |
|---|---|---|
| Lint | Lint | Bounded wiki health check — find and fix structural issues |
| Review | Review | HITL proposal queue — act on AI-proposed follow-up work |
| Deep Research | Deep Research | Web-search loop via SearXNG — synthesize and auto-ingest |
| Ingest | Ingest | Ingest run history and cost ledger |
| Convert | Convert | Dedicated Marker PDF conversion surface |
Bottom (pinned):
| Label | Section |
|---|---|
| Settings | All runtime configuration — 5 groups, 18 pages |
The vault name, data version, backend uptime, and active provider are shown in the status bar at the bottom of every section.
The command palette (Cmd/Ctrl+K) lets you jump to any section or any wiki page by typing its name. Keyboard shortcuts Cmd/Ctrl+1 through +5 switch to the first five sections; Cmd/Ctrl+N creates a new conversation in Chat.
Home dashboard¶
The Home section is the default landing screen. It loads once on mount and polls
GET /status every 10 seconds to detect vault data-version changes (only re-fetches
stats when data_version changes — no wasteful polling).
KPI row¶
Seven cards span the top:
| Card | What it shows |
|---|---|
| Pages | Total live wiki pages |
| Links | Total wikilink edges in the knowledge graph |
| Communities | Louvain communities detected (0 if graph not yet computed) |
| Review | Open HITL review items — accented when non-zero |
| Lint | Open lint findings — accented when non-zero |
| Monthly AI spend | Month-to-date provider cost in USD |
| Data version | Current data_version counter |
Recent activity¶
The ten most recently updated wiki pages, each with a relative timestamp. Clicking a row switches to the Wiki section.
Server update banner¶
When the frontend version and the backend version (from GET /status) differ and
the backend version is not "dev", a dismissible banner appears asking you to
pull the new backend image. It is stored in sessionStorage and does not reappear
unless you reload the tab.
Domain section cards¶
Below recent activity, a responsive grid shows one card per domain in your vocabulary, followed by an Unclassified card. Each card shows:
- Domain name and page count.
- A color-coded SVG mini-bar showing the type breakdown (concept / entity / source / synthesis / comparison) proportionally — computed once on mount, no charting library.
- Type counts in text form.
- Last-activity timestamp.
- Up to three most-connected pages in that domain (by graph degree).
Clicking a domain card writes the domain name to localStorage as a filter
and navigates you to the Wiki section, which loads with only that domain's pages
visible. Clicking Unclassified clears the filter and shows all untagged pages.
When no vocabulary is configured, a "No domains configured" placeholder appears with a link to Settings where you can define the vocabulary.
Wiki section¶
The Wiki section (nav label: Wiki) has a three-panel layout: a page tree on the left, a note reader/editor in the center, and a metadata inspector on the right. Both side panels are collapsible via the chevron buttons on their inner edges.
Left panel — page tree. Pages grouped by type (concept, entity, source,
synthesis, comparison). Click a row to select that page. The + button in the
panel header creates a new stub wiki page inline (title + type; one data_version
bump, no full rescan — I1).
Center panel — NoteView. Displays the raw Markdown of the selected page
(including YAML frontmatter and [[wikilinks]]). Click Edit to switch to the
CodeMirror 6 editor. Click Save to write changes back.
Save behavior:
- The backend writes the file atomically (temp file + rename).
- YAML frontmatter is validated before writing; malformed frontmatter is rejected
with 422 and the disk file is unchanged.
- Re-indexes inline: wikilinks, embeddings, graph — all for this single page, no
vault rescan (I1).
- Bumps data_version and triggers debounced graph recompute (within ~5 seconds).
- An optimistic-lock check prevents you from overwriting changes made by another
process; if a conflict is detected you receive a 409 and must reload.
Unsaved-changes guard. Navigating away from a page with pending edits shows a "Unsaved changes — continue?" dialog with Stay and Discard changes buttons.
Right panel — inspector. Shows the selected page's frontmatter (title, type, sources) and its relationships (outgoing wikilinks + pages that link back to it).
Note: the full-bleed knowledge graph lives in the dedicated Graph section (nav label: Graph), not inside the Wiki section.
Graph section¶
The full-bleed knowledge graph. This section shows only the graph canvas.
- Node size scales with the number of structural connections.
- Node color encodes page type. The legend is always visible in the bottom-left corner.
- Hover highlights the node and its immediate neighbors; everything else fades.
- Drag a node to reposition it. The position persists across graph recomputes.
- Click selects a node and announces its title for screen readers.
- The graph is polled every 5 seconds: only re-fetches if
data_versionchanged. The browser never runs a force-directed layout (I2).
Community drill-down¶
Nodes are grouped into communities by the Louvain algorithm. Click a community area to open a detail panel showing:
- Member list — every page in the community, clickable to open in Wiki.
- Cohesion score — 0–1; how tightly connected the community is internally.
A score below
GRAPH_COHESION_WARN(default 0.15) is flagged with a warning.
Edge signal breakdown¶
Click any edge to open an edge detail panel showing the four-signal decomposition:
| Signal | Coefficient | What it measures |
|---|---|---|
| Direct wikilinks | 3.0 | [[wikilinks]] between the two pages |
| Shared sources | 4.0 | Raw source files that both pages derive from |
| Adamic-Adar index | 1.5 | Common-neighbor structural similarity |
| Type affinity | 1.0 | Cross-type bonus or same-type penalty |
Sources section¶
The Sources section (nav label: Sources) is the raw source file browser. Use it to upload documents and to see all ingest runs for the current vault.
Uploading a document¶
Drag a file onto the upload zone at the top, or click Browse to open a file picker.
Accepted formats (v0.8+): Markdown, plain text (.md, .txt, .markdown), PDF,
DOCX, PPTX, XLSX, images (.png, .jpg, .jpeg, .webp), and audio/video
(.mp3, .m4a, .wav, .mp4, .mov, .webm).
Size limit: 25 MB per file (configurable via MAX_UPLOAD_BYTES). Uploading a file
whose name already exists in vault/raw/sources/ replaces and re-ingests it
(incremental — I1).
Run history¶
Each row shows status badge (Running / Completed / Failed / Did not converge), provider type, pages created, cost in USD, and a relative timestamp. Click a row to expand full details.
Run Ingest triggers a new ingest run against the current vault using the active provider. After each ingest run, the backend runs a proposal stage and enqueues review items for genuinely useful follow-up work. Visit Review to act on them.
Bulk select¶
Activate Select in the section header to enter bulk-select mode. Check rows, use Select all, then Delete selected to cascade-delete all selected source files and their derived wiki pages in one call. A dry-run summary is shown before the destructive apply.
Search section¶
The Search section supports filtering and sorting results.
Type facet. Filter chips: All, Concept, Entity, Source, Synthesis, Comparison. Click a chip to restrict results to that type; click All to clear.
Sort. A selector in the toolbar switches between:
| Option | Behaviour |
|---|---|
| Relevance (default) | Ranked by vector similarity or lexical score |
| Newest first | By created_at descending |
| Oldest first | By created_at ascending |
Both facet and sort are server-side; changing either re-fetches results immediately.
Chat section¶
The Chat section is a multi-conversation interface backed by the configured inference provider.
Left panel — conversation list. All past conversations. Create a new one with
+ or Cmd/Ctrl+N. Delete with the x on hover. Conversations persist across page
reloads. New conversations are auto-titled from the first 50 characters of your first
message. Double-click a title to rename it inline (persisted immediately).
A search box at the top filters rows in real time by title.
Center panel — message thread. Responses stream token by token. A Stop button interrupts a stream. Once a response is complete: - Regenerate re-sends your last message and replaces the previous reply. - Save to wiki creates a new wiki page from the conversation turn.
Inline citations. When the assistant answer contains [n] markers they become
clickable superscript links once streaming finishes. Clicking one opens the
referenced wiki page in the Wiki section.
Example prompts. When a conversation has no messages, three clickable chips suggest starter questions. Clicking one sends that question immediately.
Reasoning blocks. If the model produces a <think>…</think> section it is shown
in a collapsible "Reasoning" block, collapsed by default.
GFM and LaTeX. Responses are rendered as GitHub-flavored Markdown. LaTeX expressions are converted to Unicode at the end of the stream, not per token (I3).
Retrieval modes¶
The chat composer toolbar shows a segmented control labelled Retrieval mode:
| Mode | What it does |
|---|---|
| Fast | Minimal retrieval; lowest latency |
| Standard | Full 4-phase retrieval (tokenized → graph-expand → budget → assemble) — default |
| Deep | Extended graph expansion and budget; higher quality, slower |
| Local first | Prioritizes locally-stored context before vector search |
Web search toggle¶
A Web button with an emerald indicator in the composer enables or disables live web search via SearXNG for the next message. When enabled, the assistant can fetch current web sources before answering; web sources appear in a "WEB SOURCES" block in the reply.
Image attachments¶
The paper-clip button attaches up to 4 images (max 5 MB each). Only available when
the active provider reports supports_vision=true — the button is disabled with a
tooltip when vision is not supported.
Review section¶
The Review section (nav label: Review) shows the HITL proposal queue. The AI proposes follow-up work; you decide what to act on.
How proposals are generated¶
After each ingest run, Synapse runs one bounded proposal pass. This applies to API/Local and CLI providers. The delegated CLI path supplies the real source text plus bounded excerpts from only the pages written in that run; it does not scan the vault or invent a Stage-1 analysis. Rule-based proposals (missing pages, duplicates) are emitted without an LLM call.
Rules and AI have separate capacity: by default up to 8 rule proposals and 12 AI proposals, with 20 total after deduplication. A matching AI proposal wins when it carries the richer rationale or query context, so missing-link volume cannot starve detailed review suggestions.
Use the filter bar to combine status, item type, proposal origin and proposed page type. Each card
shows its origin (rule, ai, corpus, system, lint or migrated legacy), proposed type and,
after Create, the effective type that was actually written. Query badges distinguish absent,
title-only and contextual search queries before you accept a proposal.
Proposal types¶
| Type | What it means |
|---|---|
missing-page |
A referenced entity or concept has no wiki page yet |
suggestion |
A research gap the AI thinks would strengthen the vault |
contradiction |
A conflict between new content and an existing wiki page |
duplicate |
The proposed title may collide with an existing page |
confirm |
The AI wants explicit human confirmation before acting |
purpose-suggestion |
Recent content may have drifted outside purpose.md scope |
schema-suggestion |
Emerging frontmatter pattern not covered by schema.md (default off) |
The three actions¶
- Create — generates the proposed wiki page on demand, running the bounded orchestrated loop for that single page. A spinner shows while generation runs; cost is logged in the Sources run history.
- Deep Research — delegates to the Deep Research loop: Synapse runs a multi-query SearXNG web-search cycle, synthesizes findings, and auto-ingests the synthesis as a new wiki page.
- Skip — closes the proposal without action. Reversible only by re-ingesting the source.
Auto-resolution sweep¶
After each ingest run and after each Create action, a rule-based sweep closes
missing-page and duplicate proposals whose proposed_title now matches an
existing page. An optional bounded LLM pass (capped at 8 items, default on) may
close suggestion or contradiction items. confirm items are never
auto-resolved.
Corpus comparison and synthesis¶
The Home dashboard offers two explicit corpus actions when at least three eligible pages exist:
- Generate now evaluates bounded same-domain clusters and may automatically write high-confidence comparison/synthesis pages.
- Propose only performs the same bounded deterministic evaluation without requiring an
inference provider and sends eligible clusters to Review (
origin=corpus). It never writes a corpus page automatically.
Corpus generation is intentionally conservative. Every member must share a real domain/* tag;
untagged and mixed-domain candidates are skipped and counted. Run bounded domain backfill first if
the Home diagnostics report many untagged skips. The UI polls only while the operation is active
and then shows written, proposed, duplicate and untagged counts.
Each new corpus page has a stable identity derived from its kind plus sorted canonical member
paths. Re-running normally skips an existing identity before any model call. force=true may
regenerate the content but updates the same deterministic file; it does not create a second page.
Operators can inspect legacy duplicates without changing data:
GET /ops/synthesize/audit?max_pages=500
The report is dry-run only. Synapse 1.6.0 never deletes, merges, renames or backfills legacy pages automatically.
Lint section¶
The Lint section (nav label: Lint) runs a bounded health check of the wiki. Lint never modifies pages autonomously — every fix requires explicit human approval.
Running a lint scan: click Run Lint. The backend starts a bounded scan
(capped by LINT_MAX_ITER iterations and LINT_TOKEN_BUDGET tokens). A spinner
appears while the scan runs.
Finding categories:
| Category | What it flags | Actions |
|---|---|---|
orphan-page |
A page with no incoming wikilinks | Acknowledge |
contradiction |
Conflicting claims between two pages | Acknowledge |
stale-claim |
A claim that may be outdated by newer content | Acknowledge |
missing-xref |
Mentions a concept that has a page but no [[wikilink]] |
Apply or Dismiss |
Apply (only for missing-xref) inserts the missing wikilink into the page
body — a targeted edit, one data_version bump, no vault rescan (I1).
Acknowledge closes a flag-only finding without editing anything.
Dismiss discards without action.
Scheduled lint. In Settings, under the Automation page (AI behaviour group), you can schedule lint scans to run automatically at Off / Hourly / Daily / Weekly frequency. A Run now button triggers an immediate scan. Only the scan is scheduled — applying fixes is always a manual, human-approved action.
Deep Research section¶
The Deep Research section (nav label: Deep Research) runs a bounded multi-query SearXNG web-search loop and synthesizes the results into a new wiki page.
How to use:
- Navigate to Deep Research in the nav rail.
- Enter a research topic in the text field.
- Click Start Research.
Synapse runs multiple SearXNG search queries against the topic, fetches the top
results (with an SSRF guard blocking private-network addresses), assesses source
quality, refines queries, and synthesizes a wiki page from the best sources. The
run is bounded by max_iter and token_budget (I7). The synthesis is
auto-ingested into vault/wiki/ when the run completes.
All research runs are listed below the input field. Click a run to see its detail: sources fetched, cost, and the synthesis text.
Web search must be configured. The backend must have SEARXNG_URL set in the
environment, and the SearXNG instance must be reachable. Configure the URL in
Settings → AI behaviour → Web search.
Ingest section¶
The Ingest section (nav label: Ingest) is the run-history and cost ledger. Every
ingest run (triggered by the watcher, an upload, a manual trigger, or a Review Create
action) appears here. Each row shows provider, pages created, cost, and timing. v1.6.0 also exposes
an optional per-type count (entity, concept, source, query, synthesis, comparison) in
the API so generation differences between providers and runs can be diagnosed precisely.
Convert section¶
The Convert section (nav label: Convert) is the dedicated interface for the Marker PDF conversion microservice. See Higher-quality PDF extraction with Marker for full details.
4. Inference providers (F17)¶
All AI operations — ingest, chat, lint, deep research, review proposals — run through
the InferenceProvider abstraction. You choose which backend to use; no AI model is
hardcoded anywhere.
The three provider types¶
| Type | Backend | Ingest strategy | Best for |
|---|---|---|---|
| Local | Ollama on your GPU via Ollama's /api/chat |
Orchestrated loop (analyze → generate → validate → retry, max N) | Privacy-sensitive vaults; offline use; zero cost |
| API | Anthropic Messages API or any OpenAI-compatible endpoint | Orchestrated loop with native tool-calling when available | Quality + cost control; recommended default |
| CLI | claude-agent-sdk bundled CLI |
Delegated — the agent runs its own autonomous loop | Maximum quality; full agentic ingest |
Capability-aware routing is done by the backend, not you: when the active
provider has supports_agentic_loop = True (CLI only), the orchestrator delegates
the full ingest to the agent. Otherwise it runs the step-by-step orchestrated loop.
Cost tracking. Every AI call logs total_cost_usd to the database. Local Ollama
runs always log $0.0000. View the month-to-date total in Settings → System →
Costs.
Adding a provider¶
- Open Settings (bottom of the nav rail).
- Select AI & provider under the Essentials group.
- Click + Add provider.
- Choose the Type (Local / API / CLI), enter a Model ID, optionally enter a Base URL (required for non-default Ollama or OpenAI-compatible endpoints), and choose a Scope (Global or Vault).
- Click Add. The new row appears immediately.
Provider configuration precedence (most specific wins):
operation + vault_id > vault > global
API keys are NOT stored in the UI. Set
ANTHROPIC_API_KEYor your OpenAI-compatible key as an environment variable before starting the container. SeeDEPLOY.md §4for details.
Selecting the active provider¶
The header shows the currently active provider name. Click it to open the provider dropdown and switch between configured providers. The change takes effect for the next chat message or ingest run without a page reload.
CLI subscription auth¶
When the active provider is CLI (CliAgentProvider), Synapse calls the
claude-agent-sdk bundled Claude CLI. The CLI can authenticate either via
ANTHROPIC_API_KEY (pay-per-token) or via a Claude subscription OAuth token
(included with your Claude Pro/Max subscription — effectively $0 per token).
To use your subscription (no API key needed):
- On the host machine where Synapse runs, open a terminal and run:
The command prints a token starting with
claude setup-tokensk-ant-oat01-…. - Copy the full token.
- In Synapse, open Settings → Essentials → AI & provider.
- Scroll to the CLI Subscription Auth sub-section.
- Paste the token into the Subscription OAuth token field.
- Click Save.
Synapse stores the token in the application database and injects it into the Claude
CLI environment at runtime, scrubbing ANTHROPIC_API_KEY so the subscription is
used instead. The token source badge on the page shows db when a database-stored
token is active.
Security note: the token is stored in the application database in plaintext. Treat database backups accordingly. To rotate: re-run
claude setup-tokenon the host, then paste and save the new token in Settings. To revoke: click Clear on the CLI Auth section and the CLI will fall back to env / unconfigured.
v1.3.10 — live token streaming for CLI. Before v1.3.10, the CLI provider
delivered the entire chat response as a single event. As of v1.3.10, the backend
enables include_partial_messages on the claude-agent-sdk, so chat responses in
CLI mode stream token by token just like the API and Local providers. If the SDK
version does not support partial messages, the behavior degrades safely to the
previous single-event delivery.
5. Settings reference¶
Settings uses a two-column layout: a left sub-navigation list (5 groups, 18 pages) and a right content pane. Click any page item to switch without a page reload. A quick-search input at the top of the left nav filters pages by label in real time. Advanced pages are marked with an "Advanced" badge.
The default landing page is AI & provider.
Group: Essentials¶
The minimum configuration to get Synapse working.
| Page | Label | Contents |
|---|---|---|
providers |
AI & provider | LLM provider CRUD; CLI Subscription Auth sub-block |
appearance |
Appearance | Theme (Light / Dark / System), language (EN / IT) |
setup |
Setup | Context window size and budget-split bar chart; "Re-open setup wizard" button |
AI & provider lists all configured provider_config rows. Each row shows type,
model ID, and scope. Delete a provider with the row's Delete button (a warning is
shown if you are deleting the last provider). The CLI Subscription Auth block
(at the bottom of the page) is where you paste the sk-ant-oat01-… token from
claude setup-token.
Appearance controls the visual theme. Three options:
| Option | Behaviour |
|---|---|
| Light | Always light palette |
| Dark | Always dark palette |
| System | Follows the OS appearance setting live — no reload needed |
CodeMirror (the wiki editor) and the sigma.js graph canvas both follow the resolved theme automatically.
Setup — the context window selector (4K through 1M tokens). The token budget is split 60 % conversation history / 20 % retrieved context / 5 % system prompt / 15 % generation headroom; the bar chart visualizes absolute token counts. The "Re-open setup wizard" button re-launches the first-run guided wizard (backend health check → provider → PDF extractor → done). Skippable at any step.
Group: Content & sources¶
Where your data comes from and how the wiki is written.
| Page | Label | Contents |
|---|---|---|
sourceWatch |
Watched sources | Scheduled folder import (Source Watch) configuration |
clipper |
Web clipper | Chrome MV3 extension settings and token management |
pdf |
PDF extraction | PDF extractor selection (pypdf / Marker) and Marker connection settings |
generation |
Wiki generation | Conversation history length; overview language; auto-wikilink enrichment |
scenarios |
Scenarios | Five vault-purpose presets (Research, Reading, Personal Growth, Business, General) |
Watched sources. Synapse can scan a mounted folder on a schedule and import new or changed documents automatically. To use it:
- Add a bind-mount in
docker-compose.yml(e.g../import:/import:ro). - Enable the toggle on this page.
- Enter the container path (e.g.
/import) — not your host path. - Choose a frequency (15 min / 1 h / 6 h / daily).
- Click Run now to test immediately.
The scan is non-recursive by default (set IMPORT_SCAN_RECURSIVE=true to traverse
subdirectories). Capped at 200 files and 60 seconds per tick (configurable).
PDF extraction. Switch between pypdf (no microservice needed) and marker
(Marker microservice required, higher quality for scanned/complex PDFs). The
Marker service URL and Marker timeout are also editable here without a
container restart. Settings are stored in the app_config Postgres table with a
Default/Custom badge showing whether an override is active.
Wiki generation. Conversation history length (2–20 messages sent to the model
per turn). Overview language: leave blank to let the AI detect the vault's dominant
language; set an ISO code (e.g. it, en) to fix it. Auto-wikilink enrichment
toggle: when on, the post-ingest pass scans related pages for missing [[wikilinks]].
Scenarios. Apply a pre-written preset to vault/purpose.md and vault/schema.md.
Five presets: Research, Reading, Personal Growth, Business, General. Applying a
scenario overwrites both files — copy their contents elsewhere first if you have
hand-crafted them.
Group: AI behaviour [Advanced]¶
How the AI retrieves and reasons. The defaults are fine to start; change these only when you have a specific reason.
| Page | Label | Contents |
|---|---|---|
context |
Context window | Same as Setup — context window size and budget-split bar chart |
embeddings |
Embeddings | Vector-embeddings toggle and embedding-format selector |
webSearch |
Web search | SearXNG URL, categories, and max queries per Deep Research run |
automation |
Automation | Scheduled lint scan and domain backfill (frequency + Run now buttons) |
limits |
Limits & budget | Operator-class caps (review, lint, research bounds, cost alert threshold) |
Embeddings. Toggle vector embeddings on or off. When off, Qdrant is not
contacted; search degrades to Postgres lexical search. The Embedding format
selector (ollama or openai) adjusts the request/response shape when your
embedding endpoint uses the OpenAI API format. Changes apply to subsequent ingests
and queries — existing vectors are not removed or regenerated retroactively.
Web search. Configure the SearXNG instance URL. Required for Deep Research and
for the web-search toggle in Chat. The endpoint must be reachable from the backend
container (use host.docker.internal or a Tailscale IP in Docker deployments, not
localhost).
Automation (Job scheduling). Two scheduled background jobs:
- Lint scan — runs a scan on the configured frequency; applying fixes is always
manual.
- Domain backfill — re-classifies untagged pages against the current domain
vocabulary (force=false by default: skip already-tagged pages). Cheap on
subsequent runs.
Only one run per job can be in flight; a second trigger is refused. The schedule clock resets on backend restart.
Group: Access & security¶
Who can reach Synapse and how to connect other tools.
| Page | Label | Contents |
|---|---|---|
security |
Security & access | Synapse bearer token (client copy) + Cloudflare Access service token |
apiMcp |
MCP integrations | Remote MCP HTTP surface toggle, token management, Claude Desktop snippet |
Security & access is described in depth in section 6 (Accessing Synapse from outside your network) and section 7 (Authentication).
MCP integrations. The Synapse backend exposes a remote MCP server at
/mcp/server. This page shows the current token source, the allow-without-token
flag, and a ready-to-paste Claude Desktop JSON snippet. You can generate, rotate,
or clear the MCP bearer token from here without restarting the container. See
DEPLOY.md §5 for full remote MCP setup.
Group: System¶
| Page | Label | Contents |
|---|---|---|
costs |
Costs | Monthly cost rollup by provider and operation + alert indicator |
maintenance |
Maintenance | Vault maintenance actions |
about |
About | Backend version, build info |
Costs — the cost dashboard shows a monthly breakdown by provider type and
operation (ingest, chat, lint, deep research, review). A red alert indicator
appears when the month-to-date total exceeds COST_ALERT_THRESHOLD_USD (informational
only — no AI calls are blocked). Data comes from GET /costs/summary. Local Ollama
runs always show $0.0000.
Domain vocabulary. The comma-separated domain vocabulary is configured in the
Automation page (AI behaviour group) — not in a separate Advanced section. Enter
your domain names (e.g. ServiceNow, SAM, Procurement) and click Save. Empty = feature
dormant (no provider calls during ingest).
6. Accessing Synapse from outside your network¶
Synapse is designed for homelab and self-hosted deployments. The recommended network posture is: never expose the backend port directly to the public internet. Use one of the patterns below depending on your access model.
Decision table¶
| Scenario | Recommended approach |
|---|---|
| Only you, on your home LAN | Direct access (http://truenas.local:8000), no external config needed |
| You and trusted devices away from home | Tailscale mesh — private, encrypted, no public endpoint |
| Shared or public access (clipper on any machine, iOS away from home) | Cloudflare Tunnel + Cloudflare Access |
| Obsidian LiveSync / backup services inside the homelab | Tailscale or direct LAN |
Tailscale (private mesh access)¶
Tailscale creates an encrypted WireGuard mesh between all your devices. Every node
gets a stable Tailscale IP (100.x.x.x) and, with MagicDNS enabled, a hostname
(e.g. truenas.tail12345.ts.net).
To reach Synapse via Tailscale:
- Install the Tailscale client on the TrueNAS host and on your client devices (macOS, Windows, iOS, Android).
- Join both devices to the same tailnet.
- Access Synapse at
http://<tailscale-ip>:8000orhttp://<magicDNS-name>:8000.
No port-forwarding rules, no firewall exceptions, and no public endpoint needed. The traffic never leaves the Tailscale encrypted overlay.
When to use Tailscale: personal access from trusted devices (your laptop, your phone, trusted family members). Tailscale is invisible to the public internet and does not require Cloudflare Access service tokens.
Limitation: every device must have the Tailscale client installed. It is not suitable for sharing Synapse with people who won't install a VPN client.
Cloudflare Tunnel (public HTTPS endpoint)¶
Cloudflare Tunnel creates an outbound-only connection from your TrueNAS host to
Cloudflare's edge, exposing a https:// hostname without opening any inbound ports
on your router or firewall.
To set it up:
- Create a tunnel in the Cloudflare Zero Trust dashboard (Networks → Tunnels → Create a tunnel).
- Install the
cloudflareddaemon on your TrueNAS host (or as a Docker container). - Configure an ingress rule:
Hostname: synapse.yourdomain.com Service: http://localhost:8000 - Add
https://synapse.yourdomain.comtoCORS_ALLOW_ORIGINSin your.env. - Restart the Synapse stack.
The tunnel terminates TLS at Cloudflare's edge and forwards plain HTTP to your backend. Synapse receives only plain HTTP internally.
Cloudflare Access (authentication at the edge)¶
Cloudflare Access (Zero Trust) puts an authentication gate in front of the Cloudflare Tunnel before any request reaches Synapse. This is the recommended production posture introduced in v1.3.9.
Every request to https://synapse.yourdomain.com must pass the Access gate. Two
authentication paths exist depending on the client type:
Browser / PWA (interactive login)¶
When you open Synapse in a browser and have not authenticated, Cloudflare Access
redirects you to its login page (One-time PIN sent to your email, or an IdP like
Google/GitHub). After login, Cloudflare sets a CF_Authorization cookie in the
browser. Subsequent same-origin requests carry that cookie automatically.
Nothing to configure in Synapse for browser access. Leave the service-token fields in Settings blank.
Non-browser clients (service tokens)¶
The Tauri desktop app, the native iOS app, and the Chrome web clipper cannot complete the interactive login flow. They have no browser session, no cookie jar, and no way to redirect to the login page. They authenticate using a Cloudflare Access service token: two custom headers that identify the client at the edge.
CF-Access-Client-Id: <client-id>.access
CF-Access-Client-Secret: <client-secret>
Creating a service token in Cloudflare Zero Trust:
- Go to Zero Trust dashboard → Access → Service Auth → Service Tokens.
- Click Create Service Token. Give it a descriptive name (e.g. "Synapse Desktop").
- Copy the Client ID and Client Secret — the secret is shown only once.
- Go to Access Applications, open your Synapse application.
- Add a policy:
- Action: Service Auth
- Include → Service Token: select the token you just created.
- Save.
Recommendation: create one service token per client (one for the desktop app, one for the iOS app, one for the Chrome clipper). That way you can revoke any single one without affecting the others.
Configuring the service token in Synapse (desktop app and browser):
- Open Settings → Access & security → Security & access.
- Scroll to the Cloudflare Access (service token) section.
- Paste your Client ID into the "Client ID" field (e.g.
xxxxxxxx.access). - Paste your Client Secret into the "Client Secret" field.
- Click Update.
The credentials are stored in your browser's localStorage (or the desktop app's
local storage). Every API request from that client will include the
CF-Access-Client-Id and CF-Access-Client-Secret headers automatically, passing
the Cloudflare gate.
For the Chrome web clipper, the Client ID and Client Secret are entered in the extension's Options page (right-click the Synapse icon → Extension options).
For the native iOS app, the fields are in the app's Settings screen.
v1.3.10 — desktop app native HTTP. Before v1.3.10, the Tauri desktop app sent
API calls through the WebKit WebView (fetch()). Because the desktop app's origin
is tauri://localhost and the backend is cross-origin, browsers include a CORS
preflight (OPTIONS) before the real request. Cloudflare Access rejects CORS
preflights that carry service-token headers with 403, making the desktop app
unusable behind CF Access. As of v1.3.10, the desktop app routes all API calls
through the native Tauri HTTP client (@tauri-apps/plugin-http), which operates
at the Rust layer and does not trigger CORS preflights. The service token is sent
on every request without any preflight overhead, and Cloudflare Access accepts it.
The web/PWA path is unchanged.
Remote MCP behind Cloudflare Access¶
The /mcp/server endpoint has its own independent bearer token (MCP_AUTH_TOKEN).
claude.ai's web "Custom connector" UI only speaks OAuth 2.1 (see "Custom connector
(claude.ai web)" below) — Synapse ships a small OAuth 2.1/PKCE authorization server
for it (/authorize, /token, /register, 2.1.6). You have two options:
-
Claude Desktop (uses a JSON config that supports custom headers): add both the MCP bearer token and the CF-Access headers in
mcpServersconfig.{ "mcpServers": { "synapse_remote": { "type": "http", "url": "https://synapse.yourdomain.com/mcp/server", "headers": { "Authorization": "Bearer <MCP_AUTH_TOKEN>", "CF-Access-Client-Id": "<client-id>.access", "CF-Access-Client-Secret": "<client-secret>" } } } } -
claude.ai web "Custom connector" (OAuth only — no field to paste a Bearer token, and the OAuth client calls
/token//registerserver-to-server with no way to send CF-Access headers): add a Cloudflare Access policy with Action = Bypass scoped to/mcp/server,/authorize,/token,/register, and/.well-known/oauth-*. The app-level auth (the Bearer token, and — for OAuth — that same token entered once at the/authorizeconsent step) remains the gate for every one of these paths — no protection is lost, and the connector keeps working.
Custom connector (claude.ai web)¶
- Settings → Connectors → Add custom connector → URL
https://synapse.yourdomain.com/mcp/server. - Click Connect — you're redirected to Synapse's own consent page; enter your
MCP_AUTH_TOKENthere once to approve (shown pre-filled with your current token under Settings → API + MCP in this app). You're redirected back to claude.ai, now connected.
The Synapse bearer token (SYNAPSE_AUTH_TOKEN)¶
Synapse has its own optional application-level bearer token, independent of
Cloudflare Access. Set SYNAPSE_AUTH_TOKEN in your .env to require it on all
REST routes. When unset, authentication is disabled (backward-compatible with all
pre-v1.0 deployments).
Browser/PWA: when the server has a token and the client does not, the next API call returns 401 and a token-entry overlay appears. Enter the token and the request is retried automatically.
Desktop app: the Connect screen has an "Access token" field below the server URL. Enter the token before clicking Connect.
Updating the client copy. If you rotate SYNAPSE_AUTH_TOKEN on the server
(edit .env → restart the container), the stored client token becomes stale. To
update it:
- Open Settings → Access & security → Security & access.
- Paste the new token into the "Update token" field.
- Click Update. The token is saved to
localStorageimmediately — no server call is made.
This UI only updates the client copy. To rotate the server-side token, edit
SYNAPSE_AUTH_TOKENin your.envand restart the container. There is no way to rotate the server token from the UI.
To disconnect (clear the client token): click Clear on the Security & access page.
Exempt endpoints (always reachable without a bearer token even when SYNAPSE_AUTH_TOKEN
is set):
| Endpoint | Notes |
|---|---|
GET /status |
Desktop Connect screen probe |
GET /health/detailed |
Monitoring probes |
GET /docs, GET /openapi.json |
API schema |
OPTIONS (any path) |
CORS preflight cannot carry a Bearer header |
/mcp/server/* |
MCP surface has its own token |
POST /clip |
Web-clipper ingress has its own CLIP_TOKEN |
7. Authentication summary¶
There are up to three independent authentication layers in a fully-secured deployment. You may use any combination; each is optional and independent.
| Layer | What it is | Where you configure it |
|---|---|---|
| Cloudflare Access | Edge gate — blocks unauthenticated requests at the Cloudflare edge before they reach Synapse | Cloudflare Zero Trust dashboard + Settings → Security & access (service tokens for non-browser clients) |
| Synapse bearer token | Application gate — SYNAPSE_AUTH_TOKEN env var; the backend rejects all REST calls without a matching Authorization: Bearer header |
.env → restart container; client copy updated in Settings → Security & access |
| MCP bearer token | Separate gate for the /mcp/server MCP surface |
Settings → MCP integrations; or MCP_AUTH_TOKEN env var |
For a typical homelab deployment on TrueNAS with Cloudflare Tunnel:
- Cloudflare Access gates the public URL.
- Browser users authenticate via the interactive CF login.
- The desktop app, iOS app, and Chrome clipper authenticate with a CF service token
(configured in Settings → Security & access / extension Options / iOS Settings).
- SYNAPSE_AUTH_TOKEN is optional but adds defense-in-depth.
- The MCP bearer token is required if you want to connect Claude Desktop or claude.ai.
8. Opening the wiki in Obsidian¶
The vault/wiki/ folder is a valid Obsidian vault. Open it directly in Obsidian:
- In Obsidian, choose Open folder as vault and point it at
vault/wiki/. - Obsidian reads the
[[wikilinks]]and YAML frontmatter that Synapse generates. - Synapse auto-generates
vault/wiki/.obsidian/app.jsonon startup so the vault opens in reading mode by default.
You can browse, annotate, and link pages in Obsidian. Synapse will not overwrite your manual edits; it will regenerate a page only if you ingest the same source again.
v1.3.5: structured frontmatter. As of v1.3.5, every generated wiki page includes
created (preserved across regeneration) and updated (advances each write) in the
frontmatter, matching the full llm_wiki frontmatter contract.
v1.3.5: log.md format. log.md is now a narrative, day-grouped diary:
## YYYY-MM-DD headers with - HH:MM:SSZ · <verb> · <type> · [[Title]] — path
bullets. It remains append-only and machine-parseable. You can read it in Obsidian
as a human-readable history of what your vault contains.
9. Higher-quality PDF extraction with Marker¶
By default Synapse uses pypdf to extract text from PDF files. For scanned PDFs, multi-column layouts, or PDFs with embedded tables, switch to the Marker extractor — an optional Marker microservice that runs a vision model pipeline on your GPU.
Switching at runtime (no restart needed):
- Open Settings → Content & sources → PDF extraction.
- Change PDF extractor from
pypdftomarker. - Confirm the Marker service URL matches your running microservice
(default:
http://host.docker.internal:8555). - Adjust Marker timeout if needed (default 120 s — generous for large scanned PDFs).
- Click Save next to each field. A "Custom" badge confirms the override is active.
Via the Convert section. Drag up to 10 PDF files onto the Convert panel and click
Convert & ingest. Each file is processed by Marker explicitly; failures show an
inline error with no silent pypdf fallback. Successful conversions write
.extracted.md files to vault/raw/sources/ which the watcher ingests automatically.
Automatic watcher path. When PDF_EXTRACTOR=marker and the watcher picks up a
PDF dropped into vault/raw/sources/, a Marker failure silently falls back to pypdf
and logs a WARNING — only the Convert section shows errors explicitly.
10. Image captions¶
When VISION_CAPTIONS_ENABLED=true is set by the operator, Synapse generates an
AI-written caption for each ingested image file (.png, .jpg, .jpeg, .webp).
The caption becomes the wiki page body; captions are cached by SHA-256 so the same
image is never captioned twice.
This requires the active provider to report supports_vision=true. When vision is
not supported or when the flag is false (the default), image files produce a stub
placeholder page.
11. Audio and video transcription¶
When AV_TRANSCRIPTION_ENABLED=true is set by the operator, Synapse transcribes
audio and video files (.mp3, .m4a, .wav, .mp4, .mov, .webm) using a
host-side Whisper microservice before ingest.
Transcription is bounded by AV_MAX_FILES_PER_RUN (default 10) per ingest trigger.
The Whisper microservice URL is configured via WHISPER_SERVICE_URL.
Cost: zero for transcription (Whisper runs locally on your GPU).
12. Vault export and backup¶
# Vault filesystem snapshot (ZIP of raw/ + wiki/ + purpose.md + schema.md + .obsidian/)
curl -f http://localhost:8000/export \
-H "Authorization: Bearer $SYNAPSE_AUTH_TOKEN" \
-o synapse-vault-$(date +%Y%m%d).zip
# Database metadata snapshot (pages, links, edges, ingest runs, review items)
curl -f http://localhost:8000/export/data.json \
-H "Authorization: Bearer $SYNAPSE_AUTH_TOKEN" \
-o synapse-data-$(date +%Y%m%d).json
The ZIP is named synapse-vault-{vault_id}-{date}.zip and caps at 500 MB
uncompressed. The JSON object contains: pages, links, edges, runs,
review_items, exported_at, data_version.
See DEPLOY.md §17 for restore paths (vault-directory-only re-ingest or full
Postgres volume restore).
13. Domain vocabulary and auto-tagging¶
Domain sections let you slice the wiki by subject area (e.g. ServiceNow, SAM, Procurement, Regolamentazioni, TPRM).
Defining the vocabulary:
- Open Settings → AI behaviour → Automation.
- Find Domain vocabulary in the job-scheduling card area.
- Enter your domain names as a comma-separated list, e.g.:
ServiceNow, SAM, Procurement, Regolamentazioni, TPRM - Click Save.
Auto-tagging on ingest: when the vocabulary is non-empty, the ingest pipeline
runs one bounded provider call per page after it has been written. The provider
returns which vocabulary terms match; these are written to pages.tags as
domain/<Name> entries — they round-trip through YAML frontmatter and appear in
Obsidian's tag pane under the domain/ group.
Backfilling existing pages:
# Start a bounded background backfill (202 Accepted)
curl -X POST http://localhost:8000/ops/backfill-domains \
-H "Authorization: Bearer $SYNAPSE_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
Default bounds: 500 pages / 60 000 tokens. To re-classify all pages (e.g. after updating the vocabulary):
curl -X POST http://localhost:8000/ops/backfill-domains \
-H "Authorization: Bearer $SYNAPSE_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{"max_pages": 2000, "force": true}'
Check status: GET /ops/backfill-domains.
You can also schedule the backfill via Settings → AI behaviour → Automation so new/untagged pages are classified automatically.
14. Web Clipper¶
The Synapse web clipper is a Chrome MV3 browser extension. It lets you clip any web page into your vault directly from the browser.
Installing the extension:
- Download
synapse-clipper-<version>.zipfrom the GitHub releases page. - Extract the zip to a folder on your computer.
- Open Chrome →
chrome://extensions/→ enable Developer mode. - Click Load unpacked and select the extracted folder.
- The Synapse icon appears in the browser toolbar.
Configuring the extension (required before first use):
- Right-click the Synapse icon → Extension options.
- Set the Synapse Base URL to your backend (e.g.
https://synapse.yourdomain.comorhttp://localhost:8000). - Set the Clip Token to the value in Settings → Content & sources → Web clipper
(or from your
CLIP_TOKENenv var). - If you are behind Cloudflare Access, also paste your CF-Access Client ID and CF-Access Client Secret in the extension Options.
- Click Save and optionally Test Connection.
Clipping a page:
- Navigate to any web page you want to add to your vault.
- Click the Synapse extension icon.
- Review the title and Markdown preview (converted via Mozilla Readability + Turndown).
- Optionally edit the title.
- Click Clip. The extension sends the page to
POST /clip, which writes it tovault/raw/sources/and triggers normal watcher-based ingest (I1). - The page appears in the Sources section within 15–30 seconds.
The backend must have CLIP_ENABLED=true and a matching CLIP_TOKEN set. The
extension's extension ID must be added to CLIP_ALLOWED_ORIGINS.
15. Mobile and PWA¶
On screens narrower than 768 px, the navigation rail collapses to an icon-only strip (labels hidden). The three-panel Wiki section switches to a vertical stack on mobile. The sigma.js canvas supports pinch-to-zoom and two-finger pan on touch screens.
Install as PWA:
- iOS (Safari 16.4+): tap Share → Add to Home Screen.
- Android (Chrome): tap the browser menu → Install app.
Once installed, Synapse opens in standalone mode with no browser chrome. The service
worker caches the app shell for instant load. All API calls are network-first (never
served from cache — data is always fresh, preserving the dataVersion model).
16. Desktop app (Tauri v2)¶
The Synapse desktop app is a native Tauri v2 window for macOS and Windows. Download
the latest installer from the GitHub releases page. See DEPLOY.md §7 for install
instructions, unsigned-binary warnings, and build-from-source steps.
v1.3.10 native HTTP. The desktop app now routes all API calls through the Tauri
native HTTP client (@tauri-apps/plugin-http) instead of the WebKit fetch(). This
eliminates CORS preflights that Cloudflare Access would reject, making the desktop
app fully functional behind a Cloudflare Tunnel + Access gateway when the service
token is configured in Settings. The web/PWA path is unchanged.
Connect screen (first launch)¶
The first time you open the app (and after Change server), you see a full-screen Connect screen.
- Enter the base URL of your backend (scheme required, no trailing slash).
- If
SYNAPSE_AUTH_TOKENis set on the server, paste the token in the "Access token" field below the URL. - Click Connect. The app sends a
GET /statusprobe; on 2xx the URL is saved and the full interface loads.
| Backend location | URL to enter |
|---|---|
| Same machine | http://localhost:8000 |
| TrueNAS via Tailscale | http://truenas:8000 |
| Cloudflare Tunnel | https://synapse.yourdomain.com |
Server chip¶
Once connected, the header shows a chip with the backend hostname. Click it for a dropdown of up to the last 5 connected servers, plus Change server. Switching servers triggers a full page reload to flush any cross-server cached state.
Desktop-only features¶
| Feature | Shortcut / behaviour |
|---|---|
| Zoom | Cmd/Ctrl+/Cmd/Ctrl−/Cmd/Ctrl+0 — 80–140 %, persisted across restarts |
| Ingest notifications | Native OS notification on ingest completion; permission requested on first fire |
| Auto-update | Checks latest.json on GitHub on every launch; shows a banner with "Update now" / "Later"; verifies minisign signature before installing |
17. Native iOS app¶
Synapse ships a native SwiftUI iOS app (iOS 17+) in ios/. As of v2.1.0 the app has
been rebuilt as Track iOS 2.1 — a from-scratch redesign with a brand-matched design
system (same accent, jewel tones, and light/dark tokens as the desktop UI, never pure
black) and a native 5-tab shell:
| Tab | Contents |
|---|---|
| Home | Vault stats (pages/sources/links), section counts, recently-updated pages |
| Wiki | Page browser and reader (Markdown, wikilinks, mini-graph); search is one tap away from here |
| Chat | Streaming chat with tappable [n] citations |
| Graph | Interactive knowledge graph, pan/zoom/tap-to-select |
| More | Review queue, source browser, ingest activity, and settings (server, vault switch, provider, per-device tokens, appearance, language) |
Distribution. The app is not on the App Store. Build and run it yourself with
Xcode (a free Apple ID gets you a 7-day install, renewed on every rebuild — see
ios/README.md), or produce an unsigned .ipa with ios/build-unsigned-ipa.sh to
sideload via AltStore or Sideloadly. TestFlight distribution is wired up
(ios/scripts/testflight.sh) but requires a paid Apple Developer Program enrollment,
which is not yet in place — it is not currently a live distribution channel.
Cloudflare Access. The iOS app supports Cloudflare Access service tokens. Configure the Client ID and Client Secret in More → Settings → Server.
Build instructions: ios/README.md and ios/build-unsigned-ipa.sh.
18. Status bar¶
The status bar at the bottom of every section shows:
- Vault name (e.g.
default) - Data version (e.g.
v42) — increments on every page write - Uptime — how long the backend has been running
- Active provider
19. Error recovery¶
Each section is wrapped in a SectionErrorBoundary. If a section encounters an
unexpected error (e.g. a malformed API response), only that section shows an error
message with a Retry button. The rest of the app continues to work normally.
Clicking Retry remounts the failed section and re-fetches its data.
20. Runtime settings (no restart needed)¶
Nine behaviour settings can be changed from the Settings panel without editing .env
or restarting Docker. Overrides are stored in the Postgres app_config table and
take effect immediately. Each field shows a Default (grey) or Custom (teal) badge.
Click Reset to default next to any field to remove the override and revert to
the env-var baseline.
| Setting | Location in Settings | Default |
|---|---|---|
| PDF extractor | Content & sources → PDF extraction | pypdf |
| Marker service URL | Content & sources → PDF extraction | http://host.docker.internal:8555 |
| Marker timeout (s) | Content & sources → PDF extraction | 120 |
| Monthly cost alert (USD) | System → Costs | unset |
| Vector embeddings on/off | AI behaviour → Embeddings | On |
| Embedding format | AI behaviour → Embeddings | ollama |
| Overview language | Content & sources → Wiki generation | (auto) |
| Auto wikilink enrichment | Content & sources → Wiki generation | On |
| Domain vocabulary | AI behaviour → Automation | (empty) |
Infrastructure settings (DATABASE_URL, QDRANT_URL, VAULT_PATH, SYNAPSE_AUTH_TOKEN, etc.) are env-var-only and cannot be changed from the UI — they require a container restart and could cause data corruption if changed while the service is live.