# Features ## Notes Write in Markdown with a live-preview editor (Tiptap/ProseMirror). Headings, bold, italic, lists, code blocks, and task checklists render inline. A slash-command menu (`/`) inserts common blocks. **Wikilinks** — Link notes with `[[Title]]` or `[[Title|Display Text]]` syntax. Clicking a wikilink navigates to (or auto-creates) the referenced note. The editor suggests existing note titles as candidate links while typing `[[`. Backlinks appear in the note viewer sidebar. **Tags** — First-class `ARRAY[text]` column. Tag autocomplete in the editor sidebar suggests existing tags. Hierarchical tags (`project/webapp`) supported — filtering by `project` matches all `project/*` children. Tags are browsable via the knowledge graph. **Version history** — Every body edit snapshots a version (up to 20 per note). Browse and restore from the editor's History panel. Diff view shows changes against the current body. **AI writing assist** — Select a passage or work on the full document. Give an instruction ("make this more concise", "add examples"). The assistant streams a proposal; a diff view shows changes to accept or reject. Drafts persist across page loads. **Link suggestions** — The editor detects note titles appearing as plain text in the body and suggests converting them to wikilinks. ## Tasks Tasks are notes with `status IS NOT NULL`. They carry status (`todo` → `in_progress` → `done`), priority (`none`/`low`/`medium`/`high`), due date, milestone assignment, and a parent task (sub-tasks). **Task work logs** — Append progress log entries to a task with optional duration. Time tracking is visible in the task editor sidebar. **Sub-tasks** — Any task can have child tasks via `parent_id`. The task viewer shows sub-tasks inline. **Convert freely** — Convert a note to a task (sets `status=todo`) or a task back to a note from the viewer toolbar. ## Projects and Milestones **Projects** — Group related notes and tasks. Each project has a title, description, goal, status (`active`/`completed`/`archived`), and a colour. **Milestones** — Ordered stages within a project. Tasks are assigned to milestones. Milestone completion percentage shown on the project page. **Kanban view** — `/projects/:id` groups tasks by milestone in a kanban-style column layout with status-advance buttons directly on cards (→ advance, ✓ complete). **Project Workspace** — `/workspace/:projectId` opens a three-panel environment (tasks / chat / notes) locked to a project. The AI assistant creates and updates content directly in the workspace; new notes auto-load in the editor and the task list refreshes automatically after tool calls. ## Knowledge Graph `/graph` renders all notes, tasks, and tags as a D3 force-directed graph. Tag nodes cluster notes that share tags; invisible project hub nodes attract project members. Physics controls: repulsion, link distance, link strength, hub pull, gravity. Click any node to open a slide-in peek panel. Click a tag node to filter the notes list. ## AI Chat Full conversation history with SSE streaming. Features: - **RAG** — Semantically relevant notes (≥ 0.60 cosine similarity) auto-injected as context. Notes 0.45–0.60 shown in sidebar as "Suggested." - **Attach notes** — Paperclip icon to include specific notes in context. - **Project scope** — Restrict RAG to a single project's notes via the sidebar selector. - **Tool calls** — The assistant can create/update notes, tasks, projects, milestones, search the web, check weather, read RSS, query calendar events, and more. Tool calls display inline with confirm/deny for creates. - **Thinking mode** — Toggle extended reasoning for complex questions. - **Abort** — Stop button cancels in-flight generation. - **Message queue** — Messages sent while generation is in progress are queued and drained sequentially. - **Save to note** — Save any assistant reply directly as a note. - **Bulk delete** — Select and delete multiple conversations. - **Retention** — Conversations auto-pruned after configurable days (default 90). ## Daily Briefing `/briefing` is a scheduled, dialogue-based morning briefing. The assistant compiles tasks, calendar events, projects, weather forecast, and RSS digest at configurable times, then checks in throughout the day. You can reply interactively. **Schedule** — Configurable slots: morning (default 4am compile), midday (8am check-in), evening (12pm check-in), night (4pm). Scheduler catches up missed slots on startup. **Configuration** — Settings → Briefing: enable toggle, location geocoding, office days, time slot toggles, RSS feed management, push notification toggle. **RSS feeds** — Add feed URLs with optional name and category. Feeds are fetched and cached; the briefing digest includes recent items. Category badges shown in the UI. Feeds can be manually refreshed. **Weather** — Location-based forecast via Open-Meteo. Multiple locations supported (home, work, or any city name). Geocoding via Nominatim. **Profile note** — The assistant maintains a profile note for each user that it updates based on briefing conversations, improving personalisation over time. ## Web Research The assistant can search the web (SearXNG) and fetch pages, synthesising findings into notes. A lightweight `search_web` tool answers quick questions inline without saving. Requires `SEARXNG_URL` to be configured. ## CalDAV Calendar Connect an external CalDAV server (Nextcloud, Radicale, etc.) and manage calendar events via natural language. Tools: `create_event`, `list_events`, `search_events`, `update_event`, `delete_event`. Activated when user configures CalDAV credentials in Settings → Integrations. ## Sharing and Collaboration **Share** — Share any project or note/task with users or groups at `viewer`/`editor`/`admin` permission levels. Share button in the viewer/project toolbar opens a dialog. **Groups** — Admins create platform-wide groups and assign users `member`/`owner` roles. Share a resource with a group in one action. **Shared with me** — `/shared` lists all incoming shared projects and notes with permission badges. **Notifications** — Bell icon in nav shows unread count (60s polling). Notifications generated for: project shared, note shared, added to group. Click navigates to the resource. **Push notifications** — Web Push (VAPID) notifies when AI generation completes, even in another tab. Works over HTTPS only. Configurable per-user. ## Quick Capture Quick capture from the Android app routes to the intent classifier. It creates notes, tasks, or projects based on content — using the user's configured model, not the hardcoded default. ## Data Export and Backup - **Personal export** — Settings → Data: download all notes/tasks as a Markdown ZIP (with YAML frontmatter) or JSON array. - **Admin backup** — Full application backup (version 2): includes projects, milestones, task logs, AI drafts, note versions, push subscriptions. ID remapping on restore for cross-instance migration. ## PWA Installable as a desktop or mobile app. Service worker caches the shell. Push notifications handled by `public/sw.js` (suppresses duplicate notifications when the relevant tab is already focused). Works over HTTPS only in Firefox. ## Settings Settings are tabbed: | Tab | Contents | |-----|----------| | General | Assistant name, default model, model management (pull/delete) | | Account | Email change, password change, session invalidation | | Notifications | Push notification subscription, briefing push toggle | | Integrations | CalDAV configuration, SearXNG status | | Data | Personal export, backup/restore (admin) | | Briefing | Enable, location, office days, slots, RSS feeds, weather | | API Keys | Create/revoke API keys, Fable MCP download and install | | Config (admin) | Base URL, SMTP, OIDC settings | | Users (admin) | User list, invite links, registration toggle | | Logs (admin) | Error, audit, and usage logs with search | | Groups (admin) | Create/manage groups and membership | ## LLM Chat — Internal Pipeline ### Intent Routing Before the main model runs, a lightweight intent classifier (`services/intent.py`) runs concurrently with `build_context()`. It makes a fast non-streaming call (~400ms) using a smaller dedicated model (`OLLAMA_INTENT_MODEL`, default `qwen2.5:7b`) to determine if the message requires a tool call. **Skip heuristic** — Intent classification is skipped entirely for short messages (≤10 words) with no action/object keywords, saving 400–800ms on conversational replies. **Prior-work fast-path** — Phrases like "research you did", "note you made", "using your research" skip the LLM call entirely and route to null (chat), preventing `search_web` from firing when the user references existing notes. If a tool is detected, the intent's one-sentence `ack` field is streamed as the first chunk (becoming time-to-first-token), then the tool executes, then the main model generates a follow-up response with the tool result. ### Tool Loop Multi-round tool loop (max 5 rounds). All tool implementations are in `services/tools.py` with `execute_tool()` as the dispatcher. **Duplicate protection on create_note / create_task:** 1. Exact title match (case-insensitive) → hard block, redirect to `update_note` 2. Fuzzy title match (SequenceMatcher ≥ 82%; punctuation stripped before candidate search) → hard block 3. Semantic content similarity (`semantic_search_notes` threshold 0.90, body ≥ 200 chars) → soft block with `requires_confirmation: true` **Project resolution** (`_resolve_project`): 4-step lookup — (1) exact DB match, (2) `query in title` substring, (3) `title in query` reverse substring, (4) SequenceMatcher ≥ 0.55. ### Model Status Three states returned by `GET /api/chat/status`: - `not_found` — model not installed; orange indicator in header - `cold` — installed but not loaded in VRAM; yellow pulsing indicator (first request will be slow) - `loaded` — hot in VRAM; green indicator After `warmModel()` is called, a 5s polling loop runs for up to 60s until the indicator turns green. ### Context Window `OLLAMA_NUM_CTX` (default 16384) controls the context window for all generation calls. Intent classification always uses `num_ctx=4096` to reduce VRAM pressure. History summarisation kicks in at 30 messages, keeps 8 recent, summary max 400 tokens. ### Image Search `search_images` tool (SearXNG `categories=images`) fetches images server-side, stores on disk (SHA-256 dedup, 5 MB cap), and serves from `/api/images/` — the user's browser never contacts the original image host. Requires `SEARXNG_URL`. ### Web Research Pipeline Triggered by "research X and make a note" or the Research button in ChatView: 1. Intent model generates 5 focused sub-queries as a JSON array 2. All 5 SearXNG queries run in parallel (200ms stagger) 3. Up to 15 unique URLs fetched in parallel 4. Up to 12 sources passed to synthesis LLM (`num_ctx=16384`, `num_predict=8192`) 5. Note created with `tags=["research"]` SearXNG tip: add the app server IP to `botdetection.ip_lists.pass_ip` in SearXNG `settings.yml` to bypass the rate limiter for backend requests. ## Roadmap - Calendar/timeline view for tasks with due dates - Email integration (read/send via IMAP/SMTP tools in chat) - Session invalidation on user deletion - Flutter push notifications (requires FCM/APNs — separate from web VAPID) - Flutter milestone support in project view ## Keyboard Shortcuts | Key | Action | |-----|--------| | `g` + `h` | Go to Home | | `g` + `n` | Go to Notes | | `g` + `t` | Go to Tasks | | `g` + `p` | Go to Projects | | `g` + `c` | Go to Chat | | `g` (bare) | Go to Graph | | `n` | New note | | `t` | New task | | `c` | Focus chat input | | `e` | Edit current item | | `/` | Search | | `?` | Show shortcuts panel | | `j` / `k` | Navigate list items | | `Enter` | Open selected item | | `Escape` | Close panel / blur / go home (progressive) | | `Ctrl+S` | Save in editor |