diff --git a/BRAINSTORM-mcp-app-2026-02-22.md b/BRAINSTORM-mcp-app-2026-02-22.md
new file mode 100644
index 00000000..e9e90a1f
--- /dev/null
+++ b/BRAINSTORM-mcp-app-2026-02-22.md
@@ -0,0 +1,285 @@
+# BRAINSTORM: Scribe as MCP App in Claude Desktop
+
+**Mode:** Architecture | **Depth:** Deep (8 questions) | **Date:** 2026-02-22
+
+---
+
+## Context
+
+MCP Apps is a new extension to the Model Context Protocol that lets any MCP server deliver interactive UI (HTML/JS/CSS) within a sandboxed iframe inside Claude Desktop's chat window. Scribe already has a complete browser-mode fallback (IndexedDB via Dexie) that mirrors its Tauri backend 1:1 — making it uniquely well-positioned for this integration.
+
+### User Answers (8 Expert Questions)
+
+| # | Question | Answer |
+|---|----------|--------|
+| 1 | Primary use case | Write alongside Claude — draft/edit notes while chatting |
+| 2 | Data sharing | Undecided — wants pros/cons |
+| 3 | UI scope | Full app (ambitious) |
+| 4 | AI bridge | Full tool integration — notes, search, organize as MCP tools |
+| 5 | Bundling | Single HTML file (vite-plugin-singlefile) |
+| 6 | Code location | In Scribe repo (monorepo) — `src/mcp-server/` |
+| 7 | Discovery | Both: local custom connector (dev) + published (production) |
+| 8 | Deploy v1 | Local only (`npm run serve`) |
+
+---
+
+## Architecture Overview
+
+```
+┌──────────────────────────────────────────────────────────────┐
+│ Claude Desktop / claude.ai │
+│ ┌────────────────────────────────────────────────────────┐ │
+│ │ Chat Conversation │ │
+│ │ ┌──────────────────────────────────────────────────┐ │ │
+│ │ │ MCP App Iframe (sandboxed) │ │ │
+│ │ │ ┌──────────────────────────────────────────────┐│ │ │
+│ │ │ │ SCRIBE (browser mode) ││ │ │
+│ │ │ │ - Full React UI ││ │ │
+│ │ │ │ - IndexedDB persistence (Dexie) ││ │ │
+│ │ │ │ - CodeMirror editor ││ │ │
+│ │ │ │ - All features except Tauri-native ││ │ │
+│ │ │ └──────────────────────────────────────────────┘│ │ │
+│ │ │ ↕ App.connect() / postMessage │ │ │
+│ │ └──────────────────────────────────────────────────┘ │ │
+│ └────────────────────────────────────────────────────────┘ │
+│ ↕ MCP Protocol (HTTP) │
+│ ┌────────────────────────────────────────────────────────┐ │
+│ │ Scribe MCP Server (localhost:3001) │ │
+│ │ - Registers tools (create/search/edit notes) │ │
+│ │ - Serves bundled HTML as ui:// resource │ │
+│ │ - Express + StreamableHTTP transport │ │
+│ └────────────────────────────────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────┘
+```
+
+---
+
+## Quick Wins (< 2 hours each)
+
+1. **Proof of concept: static editor** — Bundle `vite build` + `vite-plugin-singlefile`, serve from a minimal MCP server, verify it renders in Claude Desktop
+2. **Platform detection for iframe** — Extend `platform.ts` to detect MCP App iframe context (no `__TAURI__`, inside iframe)
+3. **Single "open-scribe" tool** — Register one tool that renders the full Scribe UI
+
+## Medium Effort (4-8 hours)
+
+4. **Full tool suite** — Map `browserApi` operations to MCP tools: `create-note`, `search-notes`, `list-projects`, `get-note`, `update-note`
+5. **Bidirectional context** — Use `app.updateContext()` to push current note content to Claude's context window
+6. **Vite build pipeline** — Add `mcp-app` build target with singlefile plugin alongside existing Tauri/Vite builds
+7. **iframe-specific CSS** — Handle sandboxed iframe viewport: no title bar, constrained height, responsive layout
+
+## Long-term (Future sessions)
+
+8. **Data sharing via MCP server** — Server reads Scribe's SQLite DB for unified data
+9. **Published connector** — Package and list in Claude's connector directory
+10. **Theme sync** — Detect Claude Desktop's dark/light mode and match Scribe's theme
+11. **Collaborative editing** — Claude writes directly into the editor via tool calls
+
+---
+
+## Data Strategy: Pros & Cons
+
+### Option A: Independent (Sandboxed IndexedDB)
+
+| Aspect | Detail |
+|--------|--------|
+| **Pro** | Zero setup — browser mode "just works" in iframe |
+| **Pro** | No filesystem access needed — fully sandboxed |
+| **Pro** | Each Claude conversation gets its own workspace |
+| **Con** | Notes created in Claude Desktop are isolated from desktop Scribe |
+| **Con** | No cross-session persistence (iframe storage may be ephemeral) |
+| **Complexity** | Low — existing `browserApi` works unchanged |
+
+### Option B: Shared via MCP Server
+
+| Aspect | Detail |
+|--------|--------|
+| **Pro** | Unified data — notes visible in both desktop Scribe and Claude Desktop |
+| **Pro** | MCP server can read/write Scribe's SQLite DB directly |
+| **Pro** | Claude's MCP tools operate on real data |
+| **Con** | Requires server to locate and access Scribe's DB file |
+| **Con** | Concurrent access (Tauri + MCP server) needs WAL mode or locking |
+| **Con** | More complex — server becomes a data layer |
+| **Complexity** | Medium — new DB access layer in server |
+
+### Option C: Export/Import Bridge
+
+| Aspect | Detail |
+|--------|--------|
+| **Pro** | Clean separation — explicit user action to sync |
+| **Pro** | No concurrency issues |
+| **Con** | Manual friction — not seamless |
+| **Complexity** | Low |
+
+### Recommendation
+
+**Start with Option A (independent)** for v1 — it works immediately with zero changes to existing code. Plan for **Option B** in v2 when the feature proves valuable. The MCP server already has access to tools; adding SQLite read access is a natural evolution.
+
+---
+
+## MCP Tool Design
+
+### Core Tools (v1)
+
+| Tool | Description | UI? |
+|------|-------------|-----|
+| `open-scribe` | Opens the full Scribe editor in-conversation | Yes (primary) |
+| `create-note` | Creates a note with title/content | No (text result) |
+| `search-notes` | Full-text search across notes | No (text result) |
+| `get-note` | Retrieve a specific note by ID or title | No (text result) |
+| `list-notes` | List recent/all notes | No (text result) |
+
+### Extended Tools (v2)
+
+| Tool | Description | UI? |
+|------|-------------|-----|
+| `edit-note` | Update existing note content | Yes (opens editor to note) |
+| `list-projects` | Show all projects | No |
+| `create-project` | Create a new project | No |
+| `search-tags` | Find notes by tag | No |
+| `daily-note` | Open/create today's daily note | Yes (opens editor) |
+| `export-note` | Export note as markdown/PDF | No (text result) |
+
+### Tool Result → UI Flow
+
+```
+User: "Open my writing app"
+Claude: Calls open-scribe tool
+ → Host fetches ui://scribe/app.html
+ → Renders full Scribe in iframe
+ → app.ontoolresult receives initial state
+ → User writes alongside Claude
+
+User: "Create a note about our discussion"
+Claude: Calls create-note tool with title + content
+ → Returns note ID + confirmation
+ → If Scribe is open, app receives tool result and navigates to new note
+```
+
+---
+
+## Build Pipeline
+
+### New Scripts (package.json)
+
+```json
+{
+ "scripts": {
+ "mcp:build": "INPUT=src/mcp-app/mcp-app.html vite build --config vite.mcp.config.ts",
+ "mcp:serve": "npx tsx src/mcp-server/server.ts",
+ "mcp:dev": "npm run mcp:build && npm run mcp:serve"
+ }
+}
+```
+
+### Vite Config (vite.mcp.config.ts)
+
+Separate Vite config for MCP App build:
+- Uses `vite-plugin-singlefile` to inline all JS/CSS
+- Excludes Tauri-specific imports
+- Targets `src/mcp-app/mcp-app.html` as entry
+- Outputs to `dist-mcp/`
+
+### Directory Structure
+
+```
+scribe/
+├── src/
+│ ├── renderer/ # Existing React app
+│ │ └── src/
+│ │ ├── lib/ # browserApi, platform, etc.
+│ │ └── components/
+│ ├── mcp-app/ # MCP App entry point
+│ │ ├── mcp-app.html # HTML entry (loads React app)
+│ │ └── mcp-app.ts # App class + host communication
+│ └── mcp-server/ # MCP server
+│ ├── server.ts # Express + MCP SDK server
+│ ├── tools.ts # Tool definitions
+│ └── resources.ts # UI resource handler
+├── src-tauri/ # Existing Tauri backend
+├── vite.config.ts # Existing (Tauri build)
+├── vite.mcp.config.ts # New (MCP App build)
+├── dist/ # Existing (Tauri frontend)
+└── dist-mcp/ # New (MCP bundled HTML)
+```
+
+---
+
+## Iframe Constraints & Adaptations
+
+### What Works in Sandboxed Iframe
+- React rendering
+- IndexedDB / Dexie persistence
+- CodeMirror editor
+- Zustand state management
+- CSS / Tailwind styling
+- localStorage (preferences)
+- KaTeX math rendering
+- Markdown rendering (react-markdown)
+
+### What Needs Adaptation
+| Feature | Desktop | MCP App | Solution |
+|---------|---------|---------|----------|
+| Title bar / drag region | Tauri overlay | N/A | Hide via CSS class |
+| File dialogs | Tauri native | N/A | Disable export buttons |
+| Terminal panel | xterm.js + PTY | N/A | Hide terminal tab |
+| Font installation | Homebrew | N/A | Use web-safe fonts only |
+| Clipboard | Tauri API | navigator.clipboard | Already has browser fallback |
+| Window resize | Tauri window | Iframe resize | CSS max-height |
+| Global shortcuts | Tauri shortcuts | N/A | Use in-app shortcuts only |
+
+### New Platform Detection
+
+```typescript
+// src/renderer/src/lib/platform.ts (extended)
+export const isMcpApp = (): boolean => {
+ return isBrowser() && window.self !== window.top // in iframe
+}
+
+export const getPlatform = (): 'tauri' | 'browser' | 'mcp-app' => {
+ if (isTauri()) return 'tauri'
+ if (isMcpApp()) return 'mcp-app'
+ return 'browser'
+}
+```
+
+---
+
+## Security Considerations
+
+- **CSP**: `vite-plugin-singlefile` inlines everything, avoiding cross-origin issues
+- **IndexedDB isolation**: Each origin gets separate storage — MCP iframe will have its own
+- **No credential exposure**: Scribe stores no API keys in browser mode (AI features use Tauri backend)
+- **Tool authorization**: Host manages tool call approvals — users see each tool invocation
+
+---
+
+## Risk Assessment
+
+| Risk | Impact | Likelihood | Mitigation |
+|------|--------|------------|------------|
+| Bundle too large for iframe | Medium | Medium | Tree-shake unused deps, lazy-load CodeMirror |
+| IndexedDB not persistent in iframe | High | Low | Use `navigator.storage.persist()`, warn user |
+| Claude Desktop iframe size too small | Medium | Medium | Responsive CSS, collapsible sidebar |
+| MCP Apps spec changes | Low | Medium | Pin `@modelcontextprotocol/ext-apps` version |
+
+---
+
+## Recommended Path
+
+**Phase 1 (v1.17.0):** Proof of concept
+- `open-scribe` tool renders full editor in Claude Desktop
+- Independent IndexedDB storage
+- Local server only (`npm run mcp:serve`)
+- 3 additional text-only tools (`create-note`, `search-notes`, `get-note`)
+
+**Phase 2 (v1.18.0):** Full integration
+- Bidirectional context (Claude sees your writing)
+- 10+ tools covering full CRUD
+- Shared SQLite data (read from Tauri DB)
+- Published connector
+
+**Phase 3 (v1.19.0):** Polish
+- Theme sync with Claude Desktop
+- Responsive iframe layout optimization
+- Offline persistence guarantees
+- User documentation and setup guide
diff --git a/docs/reference/CLAUDE.md b/docs/reference/CLAUDE.md
index 266bfe56..7441ae49 100644
--- a/docs/reference/CLAUDE.md
+++ b/docs/reference/CLAUDE.md
@@ -199,6 +199,28 @@ npm run test # Run tests
npm run typecheck # TypeScript check
```
+### Claude Code Desktop Preview
+
+Scribe supports **in-app preview** inside Claude Code Desktop (Feb 2026+). Claude starts the Vite dev server and renders the running app in an embedded browser — auto-verifying changes by screenshotting, inspecting DOM, and clicking elements.
+
+**Config:** `.claude/launch.json` (already set up)
+
+```json
+{
+ "name": "scribe-dev",
+ "runtimeExecutable": "npm",
+ "runtimeArgs": ["run", "dev:vite"],
+ "port": 5173
+}
+```
+
+**Key details:**
+- Uses `dev:vite` (not `dev`) — runs Vite only, no Tauri compilation needed
+- App auto-detects browser mode via `platform.ts` → uses IndexedDB/Dexie for storage
+- Port 5173 matches Vite's default
+- No worktree needed — launch.json is config, not feature code
+- When opening in Claude Code Desktop, **uncheck worktree isolation** to work on `dev` directly
+
### Terminal CLI
```bash
diff --git a/docs/specs/SPEC-mcp-app-claude-desktop-2026-02-22.md b/docs/specs/SPEC-mcp-app-claude-desktop-2026-02-22.md
new file mode 100644
index 00000000..20a58351
--- /dev/null
+++ b/docs/specs/SPEC-mcp-app-claude-desktop-2026-02-22.md
@@ -0,0 +1,540 @@
+# SPEC: Scribe as MCP App in Claude Desktop
+
+> **Run Scribe's full writing environment inside Claude Desktop's conversation window via MCP Apps**
+
+**Generated:** 2026-02-22
+**Status:** Draft
+**Priority:** P1 (New Distribution Channel)
+**From Brainstorm:** [BRAINSTORM-mcp-app-2026-02-22.md](../../BRAINSTORM-mcp-app-2026-02-22.md)
+
+---
+
+## Overview
+
+MCP Apps is an extension to the Model Context Protocol that allows MCP servers to deliver interactive HTML/JS/CSS applications within a sandboxed iframe in Claude Desktop's chat window. Scribe already has a complete browser-mode fallback (`browserApi` + IndexedDB via Dexie) that mirrors the Tauri backend 1:1. This spec defines how to package Scribe as an MCP App so users can write alongside Claude — drafting and editing notes in-conversation with full tool integration.
+
+**Why this matters:** Scribe becomes the writing surface inside Claude conversations. Users stop context-switching between apps. Claude can read what you're writing, create notes, and organize your work — all within the chat.
+
+---
+
+## Primary User Story
+
+> **As a** Scribe user who also uses Claude Desktop,
+> **I want to** open Scribe directly inside my Claude conversation,
+> **So that** I can write and organize notes alongside Claude without switching windows.
+
+### Acceptance Criteria
+
+- [ ] Running `npm run mcp:serve` starts a local MCP server on `localhost:3001`
+- [ ] Adding the server as a custom connector in Claude Desktop works
+- [ ] Asking Claude to "open my writing app" renders Scribe in an iframe
+- [ ] The full Scribe UI loads (sidebar, editor, tabs, settings)
+- [ ] Notes persist across tool calls within the same conversation
+- [ ] Claude can create, search, and retrieve notes via MCP tools
+- [ ] Editor is usable at Claude Desktop's iframe dimensions
+
+---
+
+## Secondary User Stories
+
+### Claude as Writing Assistant
+
+> **As a** writer using Scribe in Claude Desktop,
+> **I want** Claude to see what I'm currently writing,
+> **So that** Claude can provide contextual suggestions, edits, and feedback.
+
+### Note Organization via Chat
+
+> **As a** knowledge worker,
+> **I want to** tell Claude "create a note about X" and have it appear in Scribe,
+> **So that** I can capture ideas from our conversation without manual copy-paste.
+
+### Quick Research Capture
+
+> **As a** researcher,
+> **I want to** ask Claude to search my existing notes while I write,
+> **So that** I can reference previous work without leaving the editor.
+
+---
+
+## Architecture
+
+### System Diagram
+
+```mermaid
+graph TB
+ subgraph "Claude Desktop"
+ Chat[Chat Conversation]
+ subgraph "Sandboxed Iframe"
+ ScribeUI[Scribe React App
browser mode]
+ IDB[(IndexedDB
Dexie)]
+ ScribeUI --> IDB
+ end
+ AppClass[App class
postMessage bridge]
+ ScribeUI <--> AppClass
+ Chat <--> AppClass
+ end
+
+ subgraph "Local Machine"
+ MCPServer[Scribe MCP Server
Express + MCP SDK
localhost:3001]
+ HTML[dist-mcp/mcp-app.html
Single-file bundle]
+ MCPServer -->|serves| HTML
+ end
+
+ Chat <-->|MCP Protocol
HTTP POST| MCPServer
+ AppClass <-->|tool calls
context updates| MCPServer
+```
+
+### Component Responsibilities
+
+| Component | Role |
+|-----------|------|
+| **MCP Server** (`src/mcp-server/server.ts`) | Registers tools, serves UI resource, handles tool execution |
+| **Tool Definitions** (`src/mcp-server/tools.ts`) | Defines MCP tools mapping to Scribe operations |
+| **Resource Handler** (`src/mcp-server/resources.ts`) | Serves bundled HTML as `ui://scribe/app.html` |
+| **MCP App Entry** (`src/mcp-app/mcp-app.ts`) | Initializes `App` class, bridges host ↔ Scribe |
+| **MCP App HTML** (`src/mcp-app/mcp-app.html`) | HTML entry point loading React app |
+| **Platform Detection** (`src/renderer/src/lib/platform.ts`) | Extended with `isMcpApp()` for iframe context |
+| **Vite MCP Config** (`vite.mcp.config.ts`) | Separate build config with `vite-plugin-singlefile` |
+
+---
+
+## API Design
+
+### MCP Tools (v1 — Phase 1)
+
+| Tool Name | Input Schema | Returns | Has UI? |
+|-----------|-------------|---------|---------|
+| `open-scribe` | `{}` (no args) | Welcome message | Yes — renders full app |
+| `create-note` | `{ title: string, content?: string, project?: string }` | Note ID + confirmation | No |
+| `search-notes` | `{ query: string, limit?: number }` | Array of matching notes (title, snippet, id) | No |
+| `get-note` | `{ id?: string, title?: string }` | Full note content | No |
+| `list-notes` | `{ project?: string, limit?: number }` | Array of note summaries | No |
+
+### MCP Tools (v2 — Phase 2)
+
+| Tool Name | Input Schema | Returns | Has UI? |
+|-----------|-------------|---------|---------|
+| `update-note` | `{ id: string, content?: string, title?: string }` | Updated note | No |
+| `delete-note` | `{ id: string }` | Confirmation | No |
+| `list-projects` | `{}` | Array of projects | No |
+| `create-project` | `{ name: string, type?: string }` | Project ID | No |
+| `search-tags` | `{ query: string }` | Matching tags with counts | No |
+| `get-daily-note` | `{ date?: string }` | Today's daily note | Yes — opens editor |
+| `export-note` | `{ id: string, format: 'markdown' \| 'html' }` | Exported content | No |
+
+### MCP Resource
+
+```
+URI: ui://scribe/app.html
+MIME: text/html; ext=mcp
+Content: Bundled single-file HTML (Scribe React app)
+```
+
+### Host ↔ App Communication
+
+```typescript
+// src/mcp-app/mcp-app.ts
+import { App } from '@modelcontextprotocol/ext-apps'
+
+const app = new App({ name: 'Scribe', version: '1.17.0' })
+app.connect()
+
+// Receive tool results (e.g., after create-note)
+app.ontoolresult = (result) => {
+ // Navigate editor to newly created note, or refresh note list
+}
+
+// Push current editor state to Claude's context
+function pushEditorContext(noteTitle: string, content: string) {
+ app.updateContext({
+ type: 'text',
+ text: `Currently editing: "${noteTitle}"\n\n${content}`
+ })
+}
+
+// Call tools from within the app
+async function createNoteFromApp(title: string, content: string) {
+ return app.callServerTool({
+ name: 'create-note',
+ arguments: { title, content }
+ })
+}
+```
+
+---
+
+## Data Models
+
+### v1: Independent IndexedDB (Sandboxed)
+
+No new data models needed. The existing `browser-db.ts` Dexie schema works unchanged:
+
+```typescript
+// Existing — works in iframe as-is
+class ScribeBrowserDB extends Dexie {
+ notes!: Table
+ tags!: Table
+ note_tags!: Table
+ note_links!: Table
+ projects!: Table
+ chat_sessions!: Table
+ chat_messages!: Table
+}
+```
+
+**Limitation:** Data is isolated per iframe origin. Notes created in Claude Desktop won't appear in desktop Scribe.
+
+### v2: Shared SQLite via MCP Server
+
+The MCP server reads Scribe's SQLite database directly:
+
+```typescript
+// src/mcp-server/db.ts (v2)
+import Database from 'better-sqlite3'
+import { homedir } from 'os'
+import { join } from 'path'
+
+// Scribe stores its DB at a known Tauri path
+const DB_PATH = join(homedir(), 'Library/Application Support/com.scribe.app/scribe.db')
+
+export function openScribeDb() {
+ return new Database(DB_PATH, { readonly: false })
+}
+```
+
+---
+
+## Dependencies
+
+### New Dependencies
+
+| Package | Purpose | Version |
+|---------|---------|---------|
+| `@modelcontextprotocol/sdk` | MCP server SDK | `^1.x` |
+| `@modelcontextprotocol/ext-apps` | MCP Apps helpers (server + client) | `^1.x` |
+| `express` | HTTP server for MCP transport | `^4.x` |
+| `cors` | CORS middleware | `^2.x` |
+| `tsx` | TypeScript execution for server | `^4.x` |
+| `vite-plugin-singlefile` | Bundle HTML + JS + CSS into one file | `^2.x` |
+
+### Dev Dependencies
+
+| Package | Purpose |
+|---------|---------|
+| `@types/express` | Express type definitions |
+| `@types/cors` | CORS type definitions |
+
+### Existing Dependencies (Reused)
+
+- `react`, `react-dom` — UI framework
+- `@uiw/react-codemirror` — Editor
+- `dexie` — IndexedDB wrapper
+- `zustand` — State management
+- `tailwindcss` — Styling
+- `lucide-react` — Icons
+- `react-markdown`, `remark-gfm` — Markdown rendering
+- `katex` — Math rendering
+
+---
+
+## UI/UX Specifications
+
+### User Flow
+
+```mermaid
+sequenceDiagram
+ actor User
+ participant Claude as Claude Desktop
+ participant MCP as MCP Server
+ participant Scribe as Scribe (iframe)
+
+ User->>Claude: "Open my writing app"
+ Claude->>MCP: call open-scribe tool
+ MCP-->>Claude: tool result + ui resource URI
+ Claude->>MCP: fetch ui://scribe/app.html
+ MCP-->>Claude: bundled HTML
+ Claude->>Scribe: render in sandboxed iframe
+ Scribe->>Scribe: Initialize (browser mode, IndexedDB)
+ Scribe-->>User: Full Scribe editor visible in chat
+
+ User->>Scribe: Write a note
+ Scribe->>Claude: app.updateContext(current note)
+ User->>Claude: "Summarize what I just wrote"
+ Claude-->>User: Summary based on editor context
+
+ User->>Claude: "Create a note called 'Meeting Notes'"
+ Claude->>MCP: call create-note
+ MCP-->>Claude: Note created (id: abc123)
+ Claude->>Scribe: ontoolresult → navigate to new note
+ Scribe-->>User: Editor opens new note
+```
+
+### Iframe Layout Adaptations
+
+| Viewport | Behavior |
+|----------|----------|
+| **Width < 600px** | Sidebar collapses to icon bar, editor fills width |
+| **Width 600-900px** | Sidebar in compact mode, editor primary |
+| **Width > 900px** | Full layout (sidebar + editor + optional panel) |
+| **Height** | `max-height: 80vh` with internal scroll on editor |
+
+### Features Hidden in MCP App Mode
+
+These features require Tauri-native APIs and are hidden when `isMcpApp()` returns `true`:
+
+| Feature | Reason | Replacement |
+|---------|--------|-------------|
+| Terminal panel | Requires PTY access | Hidden tab |
+| File export dialogs | Tauri dialog API | Download via blob URL |
+| Font installation | Requires Homebrew | Web-safe fonts only |
+| Global shortcuts | Tauri shortcut API | In-app shortcuts only |
+| Window title bar / drag region | Tauri window chrome | CSS hidden |
+| Claude chat sidebar tab | Redundant (already in Claude) | Hidden tab |
+
+### CSS Adaptations
+
+```css
+/* Applied when platform === 'mcp-app' */
+.mcp-app-mode .drag-region { display: none; }
+.mcp-app-mode .terminal-tab { display: none; }
+.mcp-app-mode .claude-tab { display: none; }
+.mcp-app-mode { max-height: 80vh; overflow: hidden; }
+.mcp-app-mode .editor-area { min-height: 400px; }
+```
+
+### Accessibility
+
+- [ ] Keyboard navigation works within iframe sandbox
+- [ ] Focus trapping respects iframe boundary
+- [ ] Screen reader announces MCP App content
+- [ ] Color contrast meets WCAG 2.1 AA within Scribe themes
+- [ ] `prefers-reduced-motion` respected in animations
+
+---
+
+## Documentation Plan
+
+### User-Facing Documentation
+
+#### 1. Setup Guide (`docs/guides/mcp-app-setup.md`)
+
+Step-by-step guide for running Scribe inside Claude Desktop:
+
+- **Prerequisites:** Node.js 18+, Claude Desktop (Pro/Max/Team), npm
+- **Installation:** `cd scribe && npm install && npm run mcp:build`
+- **Running:** `npm run mcp:serve`
+- **Connecting:** How to add custom connector in Claude Desktop settings
+ - Navigate to Settings → Connectors → Add Custom Connector
+ - Enter URL: `http://localhost:3001/mcp`
+ - Name: "Scribe"
+- **First use:** Start a new chat, ask Claude to "open Scribe"
+- **Troubleshooting:**
+ - Server not starting (port conflicts)
+ - Connector not appearing (check URL, ensure server running)
+ - Blank iframe (check browser console, rebuild)
+ - Data not persisting (IndexedDB storage limits)
+
+#### 2. MCP Tools Reference (`docs/reference/mcp-tools.md`)
+
+Complete reference for all MCP tools:
+
+- Tool name, description, input schema (with examples)
+- Response format with sample outputs
+- Which tools render UI vs. return text
+- Error responses and edge cases
+- Example prompts that trigger each tool
+
+#### 3. Architecture Guide (`docs/architecture/mcp-app.md`)
+
+Technical documentation for contributors:
+
+- System diagram (from this spec)
+- Build pipeline explanation (Vite dual-config)
+- Platform detection logic (`isTauri` / `isBrowser` / `isMcpApp`)
+- Data flow: tool call → server → response → iframe
+- Host ↔ App communication protocol
+- Security model (CSP, iframe sandbox, storage isolation)
+
+### Developer Documentation
+
+#### 4. Contributing Guide Addition (`CONTRIBUTING.md` section)
+
+New section in contributing docs:
+
+- How to develop the MCP App locally
+- Running MCP server in dev mode with hot-reload
+- Testing with the `basic-host` test harness
+- Testing with Claude Desktop (cloudflared tunnel)
+- Adding new MCP tools
+- Modifying the iframe UI
+
+#### 5. README Update
+
+New section in project README:
+
+```markdown
+## Run in Claude Desktop
+
+Scribe can run directly inside Claude Desktop as an MCP App:
+
+\`\`\`bash
+npm run mcp:build && npm run mcp:serve
+\`\`\`
+
+Then add `http://localhost:3001/mcp` as a custom connector in Claude Desktop.
+Ask Claude: "Open my writing app" — Scribe appears in your conversation.
+
+See [MCP App Setup Guide](docs/guides/mcp-app-setup.md) for details.
+```
+
+#### 6. Inline Code Documentation
+
+All new files include JSDoc headers:
+
+```typescript
+/**
+ * Scribe MCP Server
+ *
+ * Exposes Scribe's writing environment as an MCP App for Claude Desktop.
+ * Registers tools for note CRUD + search, and serves the bundled
+ * Scribe UI as an interactive resource rendered in-conversation.
+ *
+ * @see https://modelcontextprotocol.io/extensions/apps/build
+ * @module mcp-server
+ */
+```
+
+---
+
+## Integration Plan
+
+### Phase 1: Local MCP App (v1.17.0)
+
+**Goal:** Scribe renders and works inside Claude Desktop locally.
+
+| Step | Task | Files | Est. |
+|------|------|-------|------|
+| 1.1 | Install MCP dependencies | `package.json` | 15m |
+| 1.2 | Create Vite MCP config with singlefile plugin | `vite.mcp.config.ts` | 30m |
+| 1.3 | Create MCP App HTML entry point | `src/mcp-app/mcp-app.html` | 15m |
+| 1.4 | Create MCP App bridge (App class) | `src/mcp-app/mcp-app.ts` | 1h |
+| 1.5 | Extend platform detection | `src/renderer/src/lib/platform.ts` | 15m |
+| 1.6 | Add MCP-app CSS mode | `src/renderer/src/index.css` | 30m |
+| 1.7 | Hide Tauri-only features in MCP mode | Various components | 1h |
+| 1.8 | Create MCP server with Express | `src/mcp-server/server.ts` | 1h |
+| 1.9 | Define `open-scribe` tool + UI resource | `src/mcp-server/tools.ts`, `resources.ts` | 1h |
+| 1.10 | Define text-only tools (create, search, get, list) | `src/mcp-server/tools.ts` | 2h |
+| 1.11 | Build and test end-to-end | - | 1h |
+| 1.12 | Write setup guide | `docs/guides/mcp-app-setup.md` | 1h |
+| 1.13 | Write MCP tools reference | `docs/reference/mcp-tools.md` | 1h |
+| 1.14 | Update README | `README.md` | 15m |
+
+**Total estimate:** ~10-12 hours
+
+### Phase 2: Full Tool Integration (v1.18.0)
+
+| Step | Task | Est. |
+|------|------|------|
+| 2.1 | Bidirectional context (`app.updateContext()`) | 2h |
+| 2.2 | Extended tool suite (update, delete, projects, tags) | 4h |
+| 2.3 | Tool result → UI navigation (open note from tool call) | 2h |
+| 2.4 | Shared SQLite backend (server reads Tauri DB) | 4h |
+| 2.5 | Write architecture guide | 2h |
+| 2.6 | Update contributing guide | 1h |
+
+### Phase 3: Production Distribution (v1.19.0)
+
+| Step | Task | Est. |
+|------|------|------|
+| 3.1 | Published connector (Claude directory listing) | 4h |
+| 3.2 | Theme sync (detect host dark/light mode) | 2h |
+| 3.3 | Responsive iframe optimization | 2h |
+| 3.4 | Persistence guarantees (`navigator.storage.persist`) | 1h |
+| 3.5 | Cloudflare tunnel documentation | 1h |
+| 3.6 | End-to-end testing suite | 4h |
+
+### Integration with Existing Build System
+
+```
+Existing:
+ npm run dev → tauri dev (Vite + Tauri)
+ npm run build → tauri build (production binary)
+ npm run dev:vite → vite (browser-only dev server)
+
+New (added):
+ npm run mcp:build → vite build --config vite.mcp.config.ts
+ npm run mcp:serve → tsx src/mcp-server/server.ts
+ npm run mcp:dev → mcp:build && mcp:serve
+```
+
+### CI/CD Integration
+
+- Add `mcp:build` to CI pipeline to catch build failures
+- Bundle size check (warn if single HTML > 5MB)
+- MCP server smoke test (start server, call tool, verify response)
+
+---
+
+## Open Questions
+
+1. **IndexedDB persistence in sandboxed iframe** — Does Claude Desktop's iframe allow persistent IndexedDB, or is storage cleared between conversations? Needs testing.
+2. **Bundle size** — With CodeMirror + KaTeX + D3 + React, the single-file bundle may be large. Should we lazy-load heavy deps?
+3. **MCP Apps spec stability** — The spec is under active development. How should we handle breaking changes?
+4. **iframe resize events** — Does Claude Desktop resize the iframe dynamically? How do we handle viewport changes?
+
+---
+
+## Review Checklist
+
+- [ ] All new files have JSDoc documentation headers
+- [ ] Platform detection covers all three modes (tauri, browser, mcp-app)
+- [ ] MCP server starts clean with `npm run mcp:serve`
+- [ ] Single-file HTML bundle renders correctly
+- [ ] All 5 v1 tools work end-to-end
+- [ ] Tauri-only features are hidden in MCP App mode
+- [ ] Setup guide tested on a fresh machine
+- [ ] MCP tools reference has examples for every tool
+- [ ] README updated with MCP App section
+- [ ] No regressions in existing Tauri or browser builds
+- [ ] Bundle size < 5MB (target)
+
+---
+
+## Implementation Notes
+
+### Key Architectural Advantage
+
+Scribe's existing `platform.ts` + `browserApi` abstraction means the MCP App requires **zero changes** to core business logic. The entire React app runs unchanged — we're just adding a new entry point, a new build target, and an MCP server wrapper.
+
+### Bundle Size Strategy
+
+The single-file approach (`vite-plugin-singlefile`) inlines all JS/CSS/assets into one HTML file. Expected size breakdown:
+
+| Dependency | Approx. Size (gzipped) |
+|-----------|----------------------|
+| React + ReactDOM | ~45KB |
+| CodeMirror (core + markdown) | ~120KB |
+| Tailwind CSS | ~15KB |
+| KaTeX | ~90KB |
+| D3 (charts) | ~80KB |
+| Dexie | ~20KB |
+| Scribe app code | ~50KB |
+| **Total** | **~420KB gzipped** |
+
+This is well within acceptable iframe loading times.
+
+### Testing Strategy
+
+1. **Unit tests:** MCP server tool handlers (input validation, response format)
+2. **Integration tests:** Start server → call tool → verify response
+3. **Manual E2E:** Build → serve → add to Claude Desktop → verify rendering
+4. **basic-host harness:** Use MCP's test host for automated UI testing
+
+---
+
+## History
+
+| Date | Change |
+|------|--------|
+| 2026-02-22 | Initial spec created from deep architecture brainstorm |
diff --git a/package-lock.json b/package-lock.json
index 0d8470e6..c6b5f06b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "scribe",
- "version": "1.16.2",
+ "version": "1.17.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "scribe",
- "version": "1.16.2",
+ "version": "1.17.0",
"license": "MIT",
"dependencies": {
"@codemirror/lang-markdown": "^6.5.0",
@@ -17,7 +17,7 @@
"@dnd-kit/sortable": "^10.0.0",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-visually-hidden": "^1.2.4",
- "@tauri-apps/plugin-dialog": "^2.4.2",
+ "@tauri-apps/plugin-dialog": "^2.6.0",
"@types/d3": "^7.4.3",
"@types/katex": "^0.16.7",
"@uiw/react-codemirror": "^4.25.4",
@@ -42,8 +42,8 @@
},
"devDependencies": {
"@playwright/test": "^1.57.0",
- "@tauri-apps/api": "^2.9.1",
- "@tauri-apps/cli": "^2.9.6",
+ "@tauri-apps/api": "^2.10.1",
+ "@tauri-apps/cli": "^2.10.0",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.1",
"@testing-library/user-event": "^14.6.1",
@@ -195,7 +195,6 @@
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@@ -2123,7 +2122,6 @@
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.8.tgz",
"integrity": "sha512-1rASYd9Z/mE3tkbC9wInRlCNyCkSn+nLsiQKZhEDUUJiUfs/5FHDpCUDaQpoTIaNGeDc6/bhaEAyLmeEucEFPw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@codemirror/state": "^6.5.0",
"crelt": "^1.0.6",
@@ -2219,7 +2217,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18"
},
@@ -2263,7 +2260,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18"
}
@@ -2285,7 +2281,6 @@
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@dnd-kit/accessibility": "^3.1.1",
"@dnd-kit/utilities": "^3.2.2",
@@ -4425,9 +4420,9 @@
}
},
"node_modules/@tauri-apps/api": {
- "version": "2.9.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.9.1.tgz",
- "integrity": "sha512-IGlhP6EivjXHepbBic618GOmiWe4URJiIeZFlB7x3czM0yDHHYviH1Xvoiv4FefdkQtn6v7TuwWCRfOGdnVUGw==",
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz",
+ "integrity": "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==",
"license": "Apache-2.0 OR MIT",
"funding": {
"type": "opencollective",
@@ -4435,9 +4430,9 @@
}
},
"node_modules/@tauri-apps/cli": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.9.6.tgz",
- "integrity": "sha512-3xDdXL5omQ3sPfBfdC8fCtDKcnyV7OqyzQgfyT5P3+zY6lcPqIYKQBvUasNvppi21RSdfhy44ttvJmftb0PCDw==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.0.tgz",
+ "integrity": "sha512-ZwT0T+7bw4+DPCSWzmviwq5XbXlM0cNoleDKOYPFYqcZqeKY31KlpoMW/MOON/tOFBPgi31a2v3w9gliqwL2+Q==",
"dev": true,
"license": "Apache-2.0 OR MIT",
"bin": {
@@ -4451,23 +4446,23 @@
"url": "https://opencollective.com/tauri"
},
"optionalDependencies": {
- "@tauri-apps/cli-darwin-arm64": "2.9.6",
- "@tauri-apps/cli-darwin-x64": "2.9.6",
- "@tauri-apps/cli-linux-arm-gnueabihf": "2.9.6",
- "@tauri-apps/cli-linux-arm64-gnu": "2.9.6",
- "@tauri-apps/cli-linux-arm64-musl": "2.9.6",
- "@tauri-apps/cli-linux-riscv64-gnu": "2.9.6",
- "@tauri-apps/cli-linux-x64-gnu": "2.9.6",
- "@tauri-apps/cli-linux-x64-musl": "2.9.6",
- "@tauri-apps/cli-win32-arm64-msvc": "2.9.6",
- "@tauri-apps/cli-win32-ia32-msvc": "2.9.6",
- "@tauri-apps/cli-win32-x64-msvc": "2.9.6"
+ "@tauri-apps/cli-darwin-arm64": "2.10.0",
+ "@tauri-apps/cli-darwin-x64": "2.10.0",
+ "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.0",
+ "@tauri-apps/cli-linux-arm64-gnu": "2.10.0",
+ "@tauri-apps/cli-linux-arm64-musl": "2.10.0",
+ "@tauri-apps/cli-linux-riscv64-gnu": "2.10.0",
+ "@tauri-apps/cli-linux-x64-gnu": "2.10.0",
+ "@tauri-apps/cli-linux-x64-musl": "2.10.0",
+ "@tauri-apps/cli-win32-arm64-msvc": "2.10.0",
+ "@tauri-apps/cli-win32-ia32-msvc": "2.10.0",
+ "@tauri-apps/cli-win32-x64-msvc": "2.10.0"
}
},
"node_modules/@tauri-apps/cli-darwin-arm64": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.9.6.tgz",
- "integrity": "sha512-gf5no6N9FCk1qMrti4lfwP77JHP5haASZgVbBgpZG7BUepB3fhiLCXGUK8LvuOjP36HivXewjg72LTnPDScnQQ==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.0.tgz",
+ "integrity": "sha512-avqHD4HRjrMamE/7R/kzJPcAJnZs0IIS+1nkDP5b+TNBn3py7N2aIo9LIpy+VQq0AkN8G5dDpZtOOBkmWt/zjA==",
"cpu": [
"arm64"
],
@@ -4482,9 +4477,9 @@
}
},
"node_modules/@tauri-apps/cli-darwin-x64": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.9.6.tgz",
- "integrity": "sha512-oWh74WmqbERwwrwcueJyY6HYhgCksUc6NT7WKeXyrlY/FPmNgdyQAgcLuTSkhRFuQ6zh4Np1HZpOqCTpeZBDcw==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.0.tgz",
+ "integrity": "sha512-keDmlvJRStzVFjZTd0xYkBONLtgBC9eMTpmXnBXzsHuawV2q9PvDo2x6D5mhuoMVrJ9QWjgaPKBBCFks4dK71Q==",
"cpu": [
"x64"
],
@@ -4499,9 +4494,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.9.6.tgz",
- "integrity": "sha512-/zde3bFroFsNXOHN204DC2qUxAcAanUjVXXSdEGmhwMUZeAQalNj5cz2Qli2elsRjKN/hVbZOJj0gQ5zaYUjSg==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.0.tgz",
+ "integrity": "sha512-e5u0VfLZsMAC9iHaOEANumgl6lfnJx0Dtjkd8IJpysZ8jp0tJ6wrIkto2OzQgzcYyRCKgX72aKE0PFgZputA8g==",
"cpu": [
"arm"
],
@@ -4516,9 +4511,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.9.6.tgz",
- "integrity": "sha512-pvbljdhp9VOo4RnID5ywSxgBs7qiylTPlK56cTk7InR3kYSTJKYMqv/4Q/4rGo/mG8cVppesKIeBMH42fw6wjg==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.0.tgz",
+ "integrity": "sha512-YrYYk2dfmBs5m+OIMCrb+JH/oo+4FtlpcrTCgiFYc7vcs6m3QDd1TTyWu0u01ewsCtK2kOdluhr/zKku+KP7HA==",
"cpu": [
"arm64"
],
@@ -4533,9 +4528,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.9.6.tgz",
- "integrity": "sha512-02TKUndpodXBCR0oP//6dZWGYcc22Upf2eP27NvC6z0DIqvkBBFziQUcvi2n6SrwTRL0yGgQjkm9K5NIn8s6jw==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.0.tgz",
+ "integrity": "sha512-GUoPdVJmrJRIXFfW3Rkt+eGK9ygOdyISACZfC/bCSfOnGt8kNdQIQr5WRH9QUaTVFIwxMlQyV3m+yXYP+xhSVA==",
"cpu": [
"arm64"
],
@@ -4550,9 +4545,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-riscv64-gnu": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.9.6.tgz",
- "integrity": "sha512-fmp1hnulbqzl1GkXl4aTX9fV+ubHw2LqlLH1PE3BxZ11EQk+l/TmiEongjnxF0ie4kV8DQfDNJ1KGiIdWe1GvQ==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.0.tgz",
+ "integrity": "sha512-JO7s3TlSxshwsoKNCDkyvsx5gw2QAs/Y2GbR5UE2d5kkU138ATKoPOtxn8G1fFT1aDW4LH0rYAAfBpGkDyJJnw==",
"cpu": [
"riscv64"
],
@@ -4567,9 +4562,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.9.6.tgz",
- "integrity": "sha512-vY0le8ad2KaV1PJr+jCd8fUF9VOjwwQP/uBuTJvhvKTloEwxYA/kAjKK9OpIslGA9m/zcnSo74czI6bBrm2sYA==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.0.tgz",
+ "integrity": "sha512-Uvh4SUUp4A6DVRSMWjelww0GnZI3PlVy7VS+DRF5napKuIehVjGl9XD0uKoCoxwAQBLctvipyEK+pDXpJeoHng==",
"cpu": [
"x64"
],
@@ -4584,9 +4579,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-x64-musl": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.9.6.tgz",
- "integrity": "sha512-TOEuB8YCFZTWVDzsO2yW0+zGcoMiPPwcUgdnW1ODnmgfwccpnihDRoks+ABT1e3fHb1ol8QQWsHSCovb3o2ENQ==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.0.tgz",
+ "integrity": "sha512-AP0KRK6bJuTpQ8kMNWvhIpKUkQJfcPFeba7QshOQZjJ8wOS6emwTN4K5g/d3AbCMo0RRdnZWwu67MlmtJyxC1Q==",
"cpu": [
"x64"
],
@@ -4601,9 +4596,9 @@
}
},
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.9.6.tgz",
- "integrity": "sha512-ujmDGMRc4qRLAnj8nNG26Rlz9klJ0I0jmZs2BPpmNNf0gM/rcVHhqbEkAaHPTBVIrtUdf7bGvQAD2pyIiUrBHQ==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.0.tgz",
+ "integrity": "sha512-97DXVU3dJystrq7W41IX+82JEorLNY+3+ECYxvXWqkq7DBN6FsA08x/EFGE8N/b0LTOui9X2dvpGGoeZKKV08g==",
"cpu": [
"arm64"
],
@@ -4618,9 +4613,9 @@
}
},
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.9.6.tgz",
- "integrity": "sha512-S4pT0yAJgFX8QRCyKA1iKjZ9Q/oPjCZf66A/VlG5Yw54Nnr88J1uBpmenINbXxzyhduWrIXBaUbEY1K80ZbpMg==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.0.tgz",
+ "integrity": "sha512-EHyQ1iwrWy1CwMalEm9z2a6L5isQ121pe7FcA2xe4VWMJp+GHSDDGvbTv/OPdkt2Lyr7DAZBpZHM6nvlHXEc4A==",
"cpu": [
"ia32"
],
@@ -4635,9 +4630,9 @@
}
},
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
- "version": "2.9.6",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.9.6.tgz",
- "integrity": "sha512-ldWuWSSkWbKOPjQMJoYVj9wLHcOniv7diyI5UAJ4XsBdtaFB0pKHQsqw/ItUma0VXGC7vB4E9fZjivmxur60aw==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.0.tgz",
+ "integrity": "sha512-NTpyQxkpzGmU6ceWBTY2xRIEaS0ZLbVx1HE1zTA3TY/pV3+cPoPPOs+7YScr4IMzXMtOw7tLw5LEXo5oIG3qaQ==",
"cpu": [
"x64"
],
@@ -4652,9 +4647,9 @@
}
},
"node_modules/@tauri-apps/plugin-dialog": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.4.2.tgz",
- "integrity": "sha512-lNIn5CZuw8WZOn8zHzmFmDSzg5zfohWoa3mdULP0YFh/VogVdMVWZPcWSHlydsiJhRQYaTNSYKN7RmZKE2lCYQ==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.6.0.tgz",
+ "integrity": "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==",
"license": "MIT OR Apache-2.0",
"dependencies": {
"@tauri-apps/api": "^2.8.0"
@@ -4755,7 +4750,8 @@
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
@@ -5149,7 +5145,6 @@
"integrity": "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"undici-types": "~6.21.0"
}
@@ -5165,7 +5160,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
"integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.2.2"
@@ -5177,7 +5171,6 @@
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"peerDependencies": {
"@types/react": "^18.0.0"
}
@@ -5365,7 +5358,6 @@
"integrity": "sha512-rkoPH+RqWopVxDnCBE/ysIdfQ2A7j1eDmW8tCxxrR9nnFBa9jKf86VgsSAzxBd1x+ny0GC4JgiD3SNfRHv3pOg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@vitest/utils": "4.0.16",
"fflate": "^0.8.2",
@@ -5436,7 +5428,6 @@
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
@@ -5785,7 +5776,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -6490,7 +6480,6 @@
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"license": "ISC",
- "peer": true,
"engines": {
"node": ">=12"
}
@@ -6788,7 +6777,8 @@
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/dompurify": {
"version": "3.3.1",
@@ -8536,7 +8526,6 @@
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"jiti": "bin/jiti.js"
}
@@ -8811,6 +8800,7 @@
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"lz-string": "bin/bin.js"
}
@@ -10165,7 +10155,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -10328,6 +10317,7 @@
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
@@ -10343,6 +10333,7 @@
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=10"
},
@@ -10406,7 +10397,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -10419,7 +10409,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -10433,7 +10422,8 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/react-markdown": {
"version": "10.1.0",
@@ -11736,7 +11726,6 @@
"integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==",
"dev": true,
"license": "BSD-2-Clause",
- "peer": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.15.0",
@@ -11838,7 +11827,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -12420,7 +12408,6 @@
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.43",
@@ -12512,7 +12499,6 @@
"integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@vitest/expect": "4.0.16",
"@vitest/mocker": "4.0.16",
@@ -13069,7 +13055,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -13083,7 +13068,6 @@
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@@ -13520,7 +13504,6 @@
"integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"rollup": "dist/bin/rollup"
},
diff --git a/package.json b/package.json
index b3d164c8..054c22dd 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,7 @@
"@dnd-kit/sortable": "^10.0.0",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-visually-hidden": "^1.2.4",
- "@tauri-apps/plugin-dialog": "^2.4.2",
+ "@tauri-apps/plugin-dialog": "^2.6.0",
"@types/d3": "^7.4.3",
"@types/katex": "^0.16.7",
"@uiw/react-codemirror": "^4.25.4",
@@ -56,8 +56,8 @@
},
"devDependencies": {
"@playwright/test": "^1.57.0",
- "@tauri-apps/api": "^2.9.1",
- "@tauri-apps/cli": "^2.9.6",
+ "@tauri-apps/api": "^2.10.1",
+ "@tauri-apps/cli": "^2.10.0",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.1",
"@testing-library/user-event": "^14.6.1",
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 6bd6ed80..46776a21 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -15,19 +15,19 @@ name = "scribe_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
-tauri-build = { version = "2.5.3", features = [] }
+tauri-build = { version = "2.5.5", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
log = "0.4"
-tauri = { version = "2.9.5", features = [] }
+tauri = { version = "2.10.2", features = [] }
tauri-plugin-log = "2"
rusqlite = { version = "0.31", features = ["bundled"] }
uuid = { version = "1.6", features = ["v4"] }
regex = "1.10"
tauri-plugin-global-shortcut = "2.3.1"
-tauri-plugin-dialog = "2.4.2"
+tauri-plugin-dialog = "2.6.0"
chrono = "0.4.42"
lazy_static = "1.4"
dirs = "5.0"