Sovereign local AI document assistant — Rust+axum backend, SQLite, local filesystem storage, ONNX-based embeddings, Tauri shell, clean-room Svelte 5 frontend (forked from willchen96/mike upstream).
Designed to run entirely on the user's machine: no cloud database, no external auth provider, no S3 bucket. Optional LLM API keys are stored locally and never leave the box except to call the model provider the user explicitly configured.
Maintained by Semplifica s.r.l. — semplifica.ai. The code is AGPL-3.0; the Semplifica wordmark and logo are trademarks, see NOTICE.md for the brand-vs-code separation.
MikeRust is meant to be a collaborative project. Fixes, new corpus plugins, translations, jurisdiction-specific feedback, design ideas, half-formed proposals — all welcome, and a small idea filed as an issue tends to land faster than a full feature held back until it's "ready". You don't have to write the patch yourself: open an issue to discuss a direction, send a pull request when you have something concrete, or reach out at git@semplifica.ai if a public thread is the wrong place.
MikeRust derives from the open-source Mike project by Will Chen
(willchen96/mike) — an AGPL-3.0 AI legal assistant with
a TypeScript / Express / Supabase / S3 / LibreOffice stack. MikeRust
keeps the product (chat with citations, document viewer, workflows,
tabular reviews, corpora) but rebuilds both halves:
- the backend becomes a Rust+axum implementation that uses SQLite
(via
sqlite-vec) instead of Supabase + pgvector, embeds locally with ONNX (INT8-quantized multilingual-e5-base via fastembed + optional DirectML / QNN execution providers), extracts PDF / DOCX / RTF / XLSX in pure Rust — no LibreOffice process spawn — and ships as a Tauri desktop app with no server-side dependency; - the frontend is a clean-room rewrite in Svelte 5 + Vite + Tailwind CSS v4, replacing the original Next.js / React frontend — see Frontend below.
Both halves have now been rebuilt and the repository contains no
source code from the original Mike project. The Rust backend was
original from the start; the legacy React frontend — the only
Mike-derived code — has been removed from the repository and
replaced by the clean-room Svelte rewrite in frontend/. MikeRust
remains a fork of an AGPL-3.0 project and ships under AGPL-3.0 (see
License), but no Mike source survives in the tree.
For the original cloud-native upstream, see github.com/willchen96/mike. For a different sister fork specialised on Danish law, see github.com/marklok/danishmike.
A desktop window (Tauri) wrapping the Svelte frontend; the embedded axum backend runs in the same process. A few views to set expectations (screenshots are of the current Svelte UI):
The sidebar holds the Assistant, Projects, Tabular reviews, Workflows and DOCX templates, plus the recent-chats list and Settings. Light / system / dark theme toggle sits in the top bar; the AI-disclaimer is always shown under the composer.
Numeric citation pills ([1], [2], …) and [gN]/[pN] KB tags open the
source document in a resizable side panel. The viewer renders PDF / DOCX /
spreadsheets / plain text in-browser; PDF.js text-search highlights the exact
quote the model cited. Re-opening a chat re-renders all pills from persisted
annotations.
Attach a DOCX template, ask for the document, and the assistant drafts the
body and renders a print-ready .docx through the pure-Rust docx engine —
returned as a download card and previewable in the viewer.
Every field of a template is editable on a single page — identity, layout,
typography, styles and the authoring contract. System templates open
read-only and can be duplicated into editable user templates, saved as
JSON under config/docx-templates/user/.
Settings → LLM models picks the active provider — Anthropic, Google, OpenAI, Mistral, or a local OpenAI-compatible endpoint — and, for Gemini, the serving region. Only providers with a saved API key are selectable.
Every user-facing string goes through a small runes-based i18n store
(frontend/src/lib/stores/i18n.svelte.ts);
the catalogues live as plain JSON in
frontend/locales/. Currently shipped: Italian
(it.json), English (en.json), French (fr.json), German (de.json),
Spanish (es.json), Portuguese (pt.json) — six locales, identical
key tree on each (no missing strings). All six dictionaries are bundled
statically; English is the canonical locale and the fallback for any key
absent from another catalogue, so a new key is safe to ship before its
translations land.
Key parity tool.
frontend/scripts/fill-i18n.mjscarries aTtable of translations and adds any key a locale is missing, then asserts all six catalogues hold the identical key set. Adding UI strings: put the new keys in theTtable with all six languages and runnode scripts/fill-i18n.mjs.
⚠️ Development and screenshots use the UI in Italian — that's the source-of-truth surface for visual review and copy iteration. Never hardcode user-facing strings, always resolve them through ani18n.t('Namespace.key')call.
The frontend was rewritten from scratch in Svelte 5 + Vite + Tailwind CSS v4, replacing the original Next.js / React frontend.
The rewrite was done blind: from a written specification of UI
behaviour — what each screen does, which backend endpoints it calls,
what the user sees and on which interaction — never by porting,
translating or reading the React source across line by line. The point
was to carry no code dependency from the original Mike project into
this frontend. frontend/ is therefore original, independent work, not
a derivative of the upstream React code.
Svelte was chosen because it is a compiler, not a runtime framework: it emits markedly more compact code and the running UI is leaner and more reactive. MikeRust's interface is form- and panel-heavy — editors, modals, side panels, settings, tables — the kind of UI that gains little from React's virtual-DOM diffing; Svelte's compiled, fine-grained reactivity updates exactly the nodes that changed, with no vDOM layer and far less shipped JavaScript.
The Rust backend was original from the start — Mike's backend is an
Express / TypeScript stack, so nothing was carried over. The React
frontend was the only Mike-derived code in the project, and it has now
been removed from the repository. The Svelte frontend/ that
replaced it was verified independent before that removal:
- it shared no byte-identical file with the old React tree — a SHA-256 comparison of every source file in both trees found zero matches;
- the formats were disjoint — 106
.tsxReact components versus 68.sveltecomponents — so nothing could have been copied across; - every commit that touches
frontend/is authored by Dario Finardi.
The repository therefore now holds no source code from the original
Mike project — only original Rust (src/, src-tauri/) and the
original, blind-rewritten Svelte frontend (frontend/).
MikeRust currently ships Windows-only: x86_64 + ARM64 MSI
installers (the latter native on Snapdragon X Elite). macOS is on
the roadmap — work hasn't started yet, but the codebase already
compiles to aarch64-apple-darwin and the Tauri / Webview backends
are macOS-ready, so the gating items are signing / notarisation and
the equivalent of Windows Hello via Touch ID. Linux is not
supported and there are no plans to add it. Any Linux-specific
advisories that show up in the dependency graph through Tauri's GTK
chain (gtk, glib, atk, webkit2gtk, …) are therefore not
reachable in any shipped artefact — they compile on Linux but are
inert on Windows and macOS, which use webview2-com and WKWebView
respectively.
Each tagged release ships pre-built MSI installers for Windows x86_64
and ARM64. They bundle the binary plus the matching onnxruntime.dll
(1.20.0) and pdfium.dll under <install>/libs/<lib>/win-<arch>/, so
the only post-install requirement is double-clicking the installer.
dist/MikeRust_<version>_x64.msi # Windows x86_64
dist/MikeRust_<version>_arm64.msi # Windows ARM64 (Snapdragon X Elite)
Builds are produced by scripts/build-release.ps1 and attached to
the matching tag on
GitHub Releases.
Runtime logs land in <home>/mikerust-data/mike-tauri.log (see
v0.2.2 entry in HISTORY.md for the rationale).
# 1. pdfium (PDF extraction)
# Download from https://github.com/bblanchon/pdfium-binaries/releases
# Place pdfium.dll / libpdfium.so / libpdfium.dylib in libs/pdfium/
# 2. onnxruntime (embeddings via the RAG feature)
# Download the variant matching your hardware (CPU / DirectML / CUDA / CoreML / …)
# from https://github.com/microsoft/onnxruntime/releases and place the
# onnxruntime.dll / libonnxruntime.so / libonnxruntime.dylib under the
# matching libs/onnxruntime/<platform>/ subfolder. The full recipe per
# variant is in libs/onnxruntime/README.md. ort is built with
# `load-dynamic` — no statically-linked runtime, no system DLL fallback.
# 3. Backend env
cp .env.example .env
# Edit .env: set JWT_SECRET. STORAGE_PATH, DATABASE_URL etc. have sensible defaults.
# 4. Install frontend deps + Tauri CLI (one-shot)
# The Svelte frontend uses pnpm.
cd frontend && pnpm install && cd ..
# 5. Run dev (Tauri shell + axum backend + Svelte/Vite frontend)
# Preferred on Windows: use the repo-local Tauri CLI binary installed
# by pnpm under frontend/node_modules/ (version pinned by package.json,
# no global cargo-tauri required).
.\frontend\node_modules\.bin\tauri.cmd dev --config src-tauri/tauri.svelte.conf.json
# Optional alternative (only if cargo-tauri is installed globally):
# cargo tauri dev --config src-tauri/tauri.svelte.conf.json
# Or backend only (axum on 127.0.0.1:$PORT, no Tauri shell):
cargo run --features ragThe first run will:
- create
data/db/mike.db(SQLite) and apply all migrations - create
data/storage/(uploads, chat cache) - download
multilingual-e5-baseONNX weights (~280 MB) into%USERPROFILE%/mikerust-data/fastembed/on first scan / first chat with attachments
Browser / Tauri webview (Svelte + Vite :5173)
│ HTTP + SSE
▼
axum backend (127.0.0.1:<random>) ← OS-assigned high port; the Tauri
shell publishes it to the frontend
via the `api_base_url` invoke
command at boot.
Override with PORT=3001 for the
standalone-backend dev story.
├── SQLite mike.db (schema, vector store, settings)
├── sqlite-vec doc_chunks (768-dim embeddings, partition-keyed)
├── fastembed/ort multilingual-e5-base ONNX (CPU / DirectML / QNN)
├── pdfium-render PDF text extraction + page rendering
├── quick-xml+zip DOCX extraction (incl. redline detection — see below)
├── rtf-parser RTF text extraction
├── calamine XLSX/XLS/XLSB/ODS extraction
├── Local storage ./data/storage/{documents,cache}
├── LLM Anthropic / Gemini / OpenAI / vLLM / Ollama
└── MCP any HTTP/SSE MCP server, including localhost
Configure folders under Impostazioni → Documenti locali. The scanner walks the tree (honouring .gitignore-style patterns), extracts text per format, chunks at ~800 tokens with 200-token overlap, and embeds with INT8-quantized multilingual-e5-base (Xenova mirror, 768 dims, ~265 MB on disk). Embeddings live in sqlite-vec virtual tables in the same mike.db. Search queries use cosine over the partitioned vector index; partitions are keyed by (user_id, project_id_or_global) so cross-tenant retrieval is impossible.
Supported formats:
- PDF — pdfium-render native text. Per-page extraction; pages stamped with
[Page N]markers so chunks can carry locality metadata. Scanned PDFs (no embedded text) are skipped unless a vision LLM is configured. - DOCX — pure Rust ZIP+XML. Detects tracked deletions (
<w:del>) and strike-through formatting (<w:strike/>/<w:dstrike/>); both are surfaced inline as[removed by author: …]markers. See docs/DOCX.md. - RTF —
rtf-parserbody text (control words, font tables, pictures, fields stripped). - XLSX / XLS / XLSB / ODS —
calamineper-sheet flattening. - TXT / MD / CSV — UTF-8 lossy decode.
- Images / scanned PDFs — surfaced via the chat composer's vision path when the selected model is vision-capable; not indexed for RAG.
ONNX Runtime execution providers compiled in via opt-in features:
cargo build --features rag-directml # Windows GPU (DX12 device, no extra SDK)
cargo build --features rag-qnn # Qualcomm Snapdragon NPU (X Elite / 8 Gen 3)The service tries the configured EP → CPU, silently skipping providers whose DLLs aren't loadable.
Critical fix — ort/onnxruntime ABI version match (Windows 11 ARM64 / Qualcomm Snapdragon X Elite).
The vendored onnxruntime.dll in libs/onnxruntime/<platform>/ must match the exact version the current ort crate was compiled against. ABI drift even across a single minor — e.g. 1.20.0 ↔ 1.24.x — silently deadlocks TextEmbedding::try_new_from_user_defined because the function-pointer table ort builds at startup references symbols (IO bindings, plugin-EP APIs) that don't exist on the other side. No error, no log, the spawn_blocking just never returns. The current pin is ort = "=2.0.0-rc.9" / fastembed = "=4.9.1", which targets onnxruntime 1.20.0 (the rc.12 / 1.24.2 line was reverted as a preparatory step for the upcoming data-security / privacy feature — see HISTORY.md entry for 2026-05-20).
We chased this bug across three failed attempts before isolating it to ABI mismatch. The fix:
- Vendor onnxruntime 1.20.0 (the version
ort 2.0.0-rc.9actually links against — verifiable withSelect-String -Path target\debug\mike-tauri.exe -Pattern 'branch=rel-\d+\.\d+\.\d+'). Drop the matchingonnxruntime.dllfor each platform underlibs/onnxruntime/win-{arm64,x64}/; seelibs/onnxruntime/README.mdfor the fetch recipe. With the right DLL,try_new_from_user_definedreturns in ≈2.3 s on ARM64 native and ≈3.2 s on x64 under Windows' Prism emulation — equivalent to the static-link timing. ortruns inload-dynamicmode (cf.Cargo.toml:ort/load-dynamic+fastembed/ort-load-dynamic), so the runtime DLL is a distributable artifact users can swap independently of the Rust toolchain.ensure_onnxruntime_dylib_path()resolves the path at startup and exportsORT_DYLIB_PATHbefore any embedding code touches the runtime.- Default model:
Xenova/multilingual-e5-baseINT8-dynamic (~265 MB) instead of intfloat FP32 (~1.1 GB). Cross-model FP32-vs-INT8 cosine drift stays ≥ 0.97 on a curated Italian legal/insurance corpus and top-1 retrieval is preserved (seetests/embedding_perf.rs::quality_fp32_vs_int8). The INT8 path is also ~1.8× faster on batch indexing and ~3.7× lighter in RAM, so it is now the default on every platform.
When upgrading ort: rebuild, run the Select-String probe above on the new mike-tauri.exe, then bump every vendored onnxruntime.dll to match the new version. Cross-minor drift is a silent deadlock, not a build error or a runtime panic — there is no fail-fast.
Documents attached via the chat composer (the + button) land in data/storage/cache/ keyed by SHA-256 of the binary, and are pre-extracted to plain text at upload time:
data/storage/cache/<hash>.<ext> # original file
data/storage/cache/<hash>.txt # extracted plain text
Effects:
- Dedup across chats — the same file uploaded in different chats reuses the same on-disk pair (multiple
documentsrows reference one hash). - No filename collisions — two different chats can both have a file named
contratto.pdf; the hash determines the path, not the user-facing filename. - Auto re-extract on edit — modifying a docx changes its hash, so the next upload generates a fresh
.txtinstead of stale text. - Chat-delete cleanup — when a chat is deleted, the backend ref-counts each
content_hashof its linked docs and removes the on-disk binary + text only when no other doc still references that hash.
See docs/CACHE.md for the storage contract and migration history.
Assistant responses inline numeric markers ([1], [2]) plus a trailing <CITATIONS> JSON block. The frontend parses both:
- Per-marker pills —
renderMessageHtmlinfrontend/src/lib/utils/citations.tsmaps each[n]to the matching annotation byref(numeric) ordoc_id(alphanumeric[g1]/[p1]from KB hits). - DocPanel jump — clicking a pill opens the cited doc in the in-app viewer, scrolling to the cited page (PDFs) or section (DOCX).
Annotations are persisted on messages.annotations (migration 0012) so re-opening a chat re-renders all pills correctly. Page-marker contamination ([Page N] leaking into citation quotes) is sanitised on both write and read paths so PDF.js text-layer highlights work.
When the model skips the <CITATIONS> block (some providers do), synthesise_kb_citations_from_markers rebuilds citations from RAG hits keyed by (g|p)<n> tags in the response.
Impostazioni → Documenti locali (formerly "Sincronizzazione"). Add a folder, optionally scope to a project, hit Scansiona ora. Scanner emits per-file progress over the /sync/folders/:id/status endpoint with coarse pipeline stages (extracting, embedding) so the user sees motion during the slow first PDF.
The embedding model state — including the one-shot ~280 MB download — is reported via /sync/model-status; the UI renders an amber progress bar above the folder list while in downloading or loading state.
The intent. The medium-term goal for this project is a plugin system for downloading legal documents locally: a contributor (or the user) describes a new public source — Légifrance, BOE, Bundesgesetzblatt, a regional bulletin — in a small JSON manifest, and MikeRust handles the rest (sidebar entry, importer, bulk-snapshot ingestion, search, fetch, embed). No Rust patch, no rebuild, no per-corpus bespoke UI. The user keeps a fully offline mirror of the parts of public law they care about, under their own AGPL-licensed copy of MikeRust.
The first implementation lives in config/corpora-plugins/
and is documented in docs/CORPUS_PLUGINS.md.
Today three strategies are supported:
builtin— corpus served by a hand-written Rust adapter (EUR-Lex, Italian Legal). The manifest only carries metadata (display name, language list, license attribution).dila-bulk-xml— fully declarative: point at a DILA OPENDATA archive index URL, pick a fonds (CNIL / LEGI / JORF / CASS / KALI), and the generic importer takes care of download → tar walk → XML parse →corpus_documentsinsert → FTS5 index. Proof of concept: CNIL, ~26 000 délibérations indexed locally from an ~18 MB tar.gz, Etalab 2.0 license, zero anti-bot exposure.http-fetch-per-id— fully declarative keyword search + single- document fetch driven by URL templates and CSS/JSONPath extraction. Carries per-source discovery metadata (jurisdiction, doc type, auth mode, search mode, fetch format) and an optional year-filtered search endpoint. This is the live engine behind the international connectors (e-Gov, eCFR, CourtListener, OpenLegalData, BOE, …). Sources behind a JS anti-bot challenge (Cloudflare/WAF) are detected and fail loudly — for those the connector must target the source's JSON API, never its website.
Alternative under evaluation — MCP-driven backend. A second design
is on the table: instead of (or alongside) the JSON-plugin path, expose
legal-source ingestion as an MCP backend. Each public source becomes
an MCP server with tools like search, fetch, bulk_import,
list_indexed; MikeRust calls those tools the same way it already calls
any other MCP server. The trade-off is roughly:
| JSON plugins (current) | MCP backend (evaluating) | |
|---|---|---|
| Author-time cost | one JSON file | one MCP server (Rust/Python/TS) |
| Run-time cost | in-process, zero extra deps | extra long-lived process |
| Reach | bounded by the manifest schema | unbounded — arbitrary code |
| Sovereignty | data stays in data/db/mike.db |
depends on the server's policy |
| Reuse outside MikeRust | none | usable from Claude / any MCP host |
Neither path forecloses the other. The JSON plugin is shipping now because it's the smallest possible footprint; the MCP backend is being weighed for the connectors that can't be expressed declaratively (arbitrary auth flows, multi-step session protocols, jurisdiction- specific quirks like Légifrance's PISTE OAuth or the Bundesanzeiger's TOC-then-ZIP pattern). Feedback welcome — pick your favourite source and tell us which path would be less painful for it.
| Corpus | Strategy | Languages | Status |
|---|---|---|---|
| EUR-Lex (EU) | builtin (REST/SOAP + SPARQL + Cellar) | 24 EU languages | ✅ V1 — CELEX fetch via public HTML, EN fallback |
| Italia legale (HF dataset) | builtin (HF datasets-server + Parquet bulk) | Italian | ✅ V1 — Normattiva (~69K) + Corte Costituzionale (~22K) |
| CNIL (France, via DILA OPENDATA) | dila-bulk-xml plugin |
French | ✅ V1 — délibérations + recommandations + avis (~26K docs, Etalab 2.0) |
| Italian: OpenGA (TAR + Consiglio di Stato) | Same HF dataset, source filter | Italian | 🔲 in dataset, opt-in mancante |
| Italian: Cassazione (civile/penale/sez. unite) | da identificare | Italian | 🔲 V2 — sorgente fuori dataset HF |
| Italian: Normattiva post-snapshot live | URN single-fetch | Italian | 🔲 V2 — atti dopo 2026-03-01 |
| Italian: Leggi regionali (20 BUR) | per-regione | Italian | 🔲 V3 |
| Italian: Gazzetta Ufficiale (sumario quotidiano) | XML feed | Italian | 🔲 V3 |
| Italian: Decreti ministeriali / circolari | per-ministero | Italian | 🔲 V3 (import da URL) |
| French: LEGI / JORF / CASS / KALI (DILA bulk) | dila-bulk-xml plugin |
French | 🔲 — same strategy as CNIL; one manifest each |
| Légifrance (France, via PISTE) | candidate for MCP backend | French | 🔲 OAuth2 REST — JSON plugin or MCP TBD |
| Retsinformation (Denmark) | JSON /api/document/{eli} + /api/search |
Danish | planned |
| BOE (Spain) | Open Data API + daily XML sumarios | Spanish | planned |
| Gesetze im Internet (Germany) | TOC XML → per-law ZIP | German | scraping-only |
| Normattiva (Italy, direct) | none — HTML / Akoma Ntoso URN deep links | Italian | sostituito dal connettore HF; resta utile come V2 live-fetch |
Everything that contains user data lives under the workspace:
data/db/mike.db— schema, embeddings, settings, all chats, all documents metadatadata/storage/— uploads (documents/), chat cache (cache/)%USERPROFILE%/mikerust-data/fastembed/— ONNX weights (out-of-tree to avoid the Tauri watcher)data/.mikeprjenvelopes — AES-256-GCM-encrypted project bundles, key derived via Argon2id from a recipient email
No telemetry, no remote logging, no anonymous metrics. Outbound traffic only when the user explicitly invokes a remote LLM (Anthropic / Gemini / OpenAI) or a remote MCP server they configured themselves.
See .env.example for the full reference.
| Variable | Required | Default |
|---|---|---|
JWT_SECRET |
yes | — |
DATABASE_URL |
no | sqlite:<USERPROFILE>/mikerust-data/mike.db |
STORAGE_PATH |
no | %USERPROFILE%/mikerust-data/storage |
FASTEMBED_CACHE_DIR |
no | %USERPROFILE%/mikerust-data/fastembed |
PDFIUM_DYNAMIC_LIB_PATH |
no | walks ancestors of cwd / exe for libs/pdfium/ |
ORT_DYLIB_PATH |
no | walks ancestors for libs/onnxruntime/<platform>/ (see libs/onnxruntime/README.md) |
PORT |
no | 0 (OS picks a free high port — see Architecture) |
VLLM_BASE_URL |
for local LLM | — |
VLLM_API_KEY |
no | local |
ANTHROPIC_API_KEY |
for Claude | — |
GEMINI_API_KEY |
for Gemini | — |
MCP_SERVERS |
no | [] |
| Area | Status |
|---|---|
| Auth (PIN/Argon2id + Windows Hello biometric + opaque sessions) | ✅ |
| SQLite + migrations (0001 → 0030) | ✅ |
| Local storage (filesystem) | ✅ — the historical S3/R2 fallback (s3-storage feature) was removed in v0.5.2. The AWS SDK chain it pulled in pinned a vulnerable rustls 0.21.12 / rustls-webpki 0.101.7, and the feature was never wired into make_storage to begin with. |
| PDF extraction (pdfium) + scanned-PDF detection | ✅ |
| DOCX extraction with redline detection | ✅ |
| RTF / XLSX / TXT / MD / CSV extraction | ✅ |
| RAG: scanner, chunker, sqlite-vec, fastembed CPU | ✅ |
| RAG: DirectML / QNN execution providers | ✅ opt-in |
| LLM: Anthropic / Gemini / OpenAI / vLLM / Ollama | ✅ |
| MCP client (HTTP/SSE) — synchronous tools | ✅ |
| MCP client — multi-step async flows (request → poll → fetch) | |
| Routes: auth, user, chat, documents, projects, workflows, docx-templates, sync, tabular-review, corpora | ✅ |
| Project: documents (PDF/DOCX/RTF/XLSX) + folders + versions + rename | ✅ |
| Project: chats list, tabular-reviews list, owner/shared visibility | ✅ |
Project: URL ?tab= deep-linking (documents / assistant / reviews) |
✅ |
Project: .mikeprj AES-256-GCM export + import |
✅ |
| Chat citations with persistence | ✅ |
| Chat-attachment hash cache + ref-counted cleanup | ✅ |
Accept / Reject decision on generated docx (migration 0029) — per-chat decision (accepted / rejected) on every docx the model emits; rejection requires a user motive and triggers a one-shot LLM summary; subsequent chat turns inject the reason + summary in place of the rejected body so the model can correct itself without re-seeing the vetoed bytes. A read-only "Vedi riassunto" modal re-opens the archived reason + summary after the reject modal closes; flipping back to Accept restores the original document while keeping the audit trail. |
✅ |
Chat-files popover in the composer footer — surfaces all five categories the chat ever touched: uploaded attachments, tool-generated docs, rejected docs (strikethrough + red Rifiutato badge), project-inherited docs (chats.project_id → documents.project_id) and KB / corpora docs cited via messages.annotations. Per-format icon colours (Excel green / Word blue / PDF red / PowerPoint orange / Markdown text-primary); origin tag chips colour-coded by category. Reads exclusively from GET /chat/:id/documents. |
✅ |
App version badge next to "MikeRust" in the sidebar + License panel in Settings → Licenza (SPDX AGPL-3.0-only, plain-language summary, full bundled LICENSE text) |
✅ |
HyDE — Hypothetical Document Embeddings (migration 0030, v0.5.0) — opt-in toggle in Settings → Recupero documenti. When ON, retrieve_kb_chunks drafts a domain-aware pseudo-answer (anchored on the legal/medical/finance/… prologue), embeds it, runs a second KNN, and merges the two rankings via Reciprocal Rank Fusion (k=60) before the usual top-K + 0.75 distance threshold + PII filter. Default OFF (adds one LLM call per turn). |
✅ |
DirectML execution provider compiled into the MSI (Windows DX12 GPU). ort tries DirectML at runtime; falls back to CPU automatically on machines without a DX12 adapter. No knob — transparent acceleration. |
✅ |
Citation pipeline normalisers (v0.5.1) — model-independent post-processors that survive the variability of mid-tier LLMs: hybrid bracket splitter ([c1, c2, FILE.pdf, p.4, doc-7] → clean per-citation pills, stops at <CITATIONS>), cross-message [cN] lookup (re-resolves a marker against earlier assistant turns when the current turn forgot to re-emit it), plus five new explicit CITATION QUALITY RULES in MRUST_SYSTEM_PROMPT (omit empty quotes, ranges only with [[PAGE_BREAK]], prefer per-passage + attached-doc citations, re-emit cross-turn [cN]). |
✅ |
Cross-provider determinism (v0.5.1) — temperature = 0.5 on Anthropic / OpenAI / local-OpenAI-compatible; max_tokens 4096 → 8192 on Claude + local for trailing <CITATIONS> JSON headroom. Gemini sampler rolled back to its API default in v0.5.1b for versatile heterogeneous-document analysis — tightening gemini-2.5-flash to 0.5 triggered a long-context white-out (model loops on whitespace until the stream limit). |
✅ |
Orphan KB cleanup (v0.5.1) — retrieve_kb_chunks probes each chunk's source_path and drops missing files at chat-time; new POST /sync/cleanup-orphans cascades through documents + doc_chunks + synced_files; viewer surfaces a "Pulisci sorgenti rimosse" modal when a citation source 404s. |
✅ |
DocxView A4 fit + reflow toggle (v0.5.1) — preserves A4 page geometry (width + height + margins, breakPages: true) and auto-scales via CSS zoom = containerWidth / pageWidth (clamped [0.4, 1.5]) through a ResizeObserver when the user drags the side-panel divider; top-right toggle flips to a reflow mode for narrow side-panel reading. |
✅ |
Authoritative-corpus framework (LegalCorpusAdapter trait) |
✅ |
| EUR-Lex V1 (CELEX-based fetch + 24-language picker + EN fallback) | ✅ |
| EUR-Lex V2 (full-text search via SOAP CWS) | 🔲 registration required |
| Italia legale V1 (Normattiva + Corte Cost via HF dataset) | ✅ |
| Italia legale V2 (OpenGA opt-in, Cassazione, live Normattiva) | 🔲 see CORPORA.md |
| Italia legale V3 (regional laws, GU, ministerial decrees) | 🔲 |
JSON-manifest plugin system (config/corpora-plugins/*.json) |
✅ schema + loader + adapter registry + generic /corpora routes + discovery metadata, per-corpus enable/disable, unified year-filter search, dev hot-reload |
dila-bulk-xml strategy (download tar.gz → walk XML → FTS5) |
✅ end-to-end test + live import |
| CNIL via DILA OPENDATA (declarative plugin) | ✅ — first proof-of-concept consumer of the plugin system |
| Other DILA fondi (LEGI, JORF, CASS, KALI) as plugins | 🔲 — same strategy, one manifest each |
| MCP-backend alternative for ingestion (Légifrance / Bundesanzeiger / …) | 🔲 design phase — see "Authoritative legal corpora" |
| Other corpus ingestors (Retsinformation, BOE, …) | 🔲 planned |
| Professional-domain column across workflows / tabular_reviews / projects / documents (migration 0018) | ✅ 11 canonical domains (legal, medical, finance, real_estate, hr, insurance, ip, compliance, gdpr, pa, others), validated at API boundary, filter chips in list views |
Per-user default_domain preference (migration 0019, Account → Generali UI) |
✅ pre-selects in every create / picker modal |
Per-user enabled_domains toggle (migration 0027, Impostazioni → Domini) |
✅ persists subset of visible verticals server-side; NULL = all enabled; downstream filtering of pickers is a follow-up |
Per-file PII redaction — GLiNER2 zero-shot multilingual NER behind the ner-pii feature; per-file checkbox in the chat composer (( PII [☐] filename ✕ )) + per-chat disclaimer modal (Enter / Esc keybinds, link to Omissis via system browser); 2000-char chunked extraction with [LABEL] redaction over the extracted text before it reaches the cloud LLM; manual HF bootstrap with byte-level download progress in the same banner as the embedding model. The whole stream_chat pipeline runs inside a single tokio::spawn so Sse::new returns immediately — doc_extract_* and pii_redact_* SSE events render a "Estrazione testo → Anonimizzazione PII n / N" progress strip inside the assistant turn the moment each stage fires (no more silent wait on long PDFs) |
|
JSON-driven workflow & column-preset registries (config/workflow-presets/ + config/column-presets/) |
✅ in-memory loaders, no DB seed, merged into /workflow list; replaces the legacy TS constants |
| Built-in workflows shipped (legal vertical) | ✅ 14 — Generate CP Checklist, NDA Review, SPA Review, Credit Agreement Review/Summary, Commercial Agreement/Lease/Supply Review, LPA, Shareholder Agreement Review/Summary, Change of Control Review, E-Discovery Review, Employment Agreement Review |
| Built-in workflows shipped (insurance vertical) | ✅ 6 — 3 tabular comparison (RC Professionale, RC Prodotti, D&O, 24 cols each) + 3 assistant (Riassunto copertura, Due Diligence assicurativa, Inventario beni assicurati) |
| Insurance phase-2 workflows (Cyber / RC Generale / Property review / RC Medica / Key Man) | 🔲 see docs/insurance-workflows-plan.md |
| Built-in workflows shipped (medical-legal vertical) | ✅ 11 — 7 tabular (inventario documenti, timeline cronologica, diagnosi strumentali con flag DIRETTA/INDIRETTA/ESCLUSIVA, ITT, IP-RC SIMLA, MIP INAIL, invalidità civile DM 1992) + 4 assistant (diagnosi ingresso, diagnosi dimissione, nesso causale 6.1→6.6, quality check 10 punti). Map dei 7 moduli di docs/piano_toolkit_medico_legale.md + DOCX template it/relazione-medico-legale per la stesura finale. |
| Built-in workflows shipped (finance / commercialista vertical) | ✅ 22 — 17 tabular (inventario, scadenzario fiscale annuale, portafoglio clienti, quality-check pre-invio, riclassificazione bilanci pluriennale, indicatori economico-finanziari, metodi valutativi, contestazioni accertamento, analisi bancaria Art. 32, rideterminazione reddito, indicatori di crisi CCII, stato passivo per rango, confronto piano vs liquidatoria, cash-flow previsionale, checklist DD documenti, rischi DD con semaforo, esposizione fiscale anno×tributo, rilievi-controdeduzioni, scadenze processuali, checklist redditi PF) + 5 assistant (relazione stima d'azienda, relazione CTU tributaria, attestazione Art. 33 CCII, report due diligence, ricorso tributario D.Lgs. 546/92). Map delle 6 aree di docs/piano_toolkit_commercialista.md + 3 DOCX template (it/relazione-stima-valore, it/attestazione-art-33-ccii, it/ricorso-tributario). |
| Column-preset shortcuts (auto-suggest column prompt+format from name match) | ✅ 13 legal + 17 insurance, domain-scoped auto-match |
| Picker modals with on-the-fly domain switch | ✅ workflow / template / tabular-template / column-preset pickers all expose a DomainSelect combo, pre-seeded with the user's default at every open |
LLM model catalogue (config/model.json + GET /models) |
✅ 4 providers (Anthropic, Google Gemini, OpenAI, Mistral), Gemini 30-region matrix, preview/legacy flags drive auto-snap to global + UI dimming |
| Settings → Modelli LLM: catalogue-driven combos | ✅ model and region dropdowns populated from /models; "Provider attivo" buttons gated to providers with a saved API key (lock icon + tooltip for the rest) |
| Chat model picker filters out unconfigured providers | ✅ ModelToggle hides Anthropic / OpenAI / Gemini until their API key is saved, matching the Settings page gating |
Six UI locales (it / en / fr / de / es / pt) |
✅ full catalogues, identical key tree, English fallback for any missing key via the i18n store |
| Language picker | ✅ in Settings → Profile |
| DOCX templates screen — list, detail, generate, apply-to-chat | ✅ filter by domain / locale / free-text; detail modal renders the auto-generated authoring contract; "Apply to chat" opens a fresh conversation with the template attached |
| DOCX template editor (full-page) | ✅ edits every DocxTemplate field — identity, layout, typography, styles, authoring contract; system templates open read-only and duplicate into editable user templates; user templates persist as JSON under config/docx-templates/user/ via POST /docx-templates/save |
| Hide / unhide DOCX templates | ✅ per-user, with Tutti / Predefiniti / Personalizzati / Nascosti tabs (migration 0024) |
| Prompt translation | ✅ the workflow and DOCX-template editors translate their free-text fields into a language chosen in a modal; runs through a bounded-concurrency pool with a per-request timeout and live progress |
| Prompt caching + window-aware summarization | ✅ the stable system prefix is sent with Anthropic cache_control (Gemini gets implicit caching); conversation history is compressed once the whole prompt — system prefix + attached docs + history — passes 80% of the model's context window |
| Frontend unit tests (vitest) | ✅ citation / highlight / markdown utilities + a DOCX-template-editor mount test |
The MCP client successfully discovers servers and dispatches synchronous tool calls (a tool that returns its real result on the same call). What is not yet reliably handled is the multi-step async pattern that human-in-the-loop MCP servers use — Edge / Semplifica.Edge being the canonical case:
Mike → request_pseudonymized_documents → {session_id, status:"pending"}
(Edge waits for the human to approve in its GUI)
Mike → get_pseudonymized_documents → list of pseudonymised files
Mike → count entities / download text → next tools in the chain
Today Mike's auto-chain wrapper covers the immediate request_* →
get_* hop (with a 300 s timeout, configurable via
MCP_CALL_TIMEOUT_SECS), but a third-step or beyond — "list the
pseudonymised files, count their entities, download the pseudonymised
text" as separate tool invocations within the same conversational turn —
is not driven correctly by the dispatcher yet. The user has to nudge the
chat to perform each subsequent step manually.
Tracked as work-in-progress; do not modify MRUST_SYSTEM_PROMPT or
build_mcp_system_prompt when fixing this — the prompt structure is
preserved, only the dispatcher mechanics are in scope. See
src/routes/chat.rs dispatch_mcp_tool_with_async_chain.
- docs/MANUAL.md — operator manual (running, troubleshooting, recovery)
- docs/DOCX.md — DOCX extraction details (tracked changes, strikes, namespaces)
- docs/CACHE.md — chat-attachment cache layout + ref-counting
- docs/CORPORA.md — EUR-Lex + national legal-corpora plan + API survey
- docs/EURLEX_REGISTRATION.md — EUR-Lex V1 (no auth) + V2 SOAP registration steps
- docs/SESSION_RECAP.md — historical session notes
- docs/UPSTREAM_SYNC.md — policy + audit log for syncing fixes from upstream
willchen96/mike - docs/CORPUS_PLUGINS.md — JSON-manifest plugin system for legal corpora (schema, strategies, add-a-corpus guide)
- docs/WORKFLOWS.md — user manual for Workflows, Tabular Reviews, and Assistant injection. Includes 7 non-legal examples (medical, finance, real estate, HR, insurance, IP, compliance) for designing your own templates.
- HISTORY.md — release notes / changelog, date-grouped
- For the pristine upstream README, see
willchen96/mikedirectly
MikeRust is a fork of the AGPL-3.0 willchen96/mike project and ships under AGPL-3.0. The backend (src/, src-tauri/) is original Rust and the frontend/ is an original clean-room Svelte rewrite; both ship under the same license for consistency. See LICENSE.
Brand assets are not AGPL. The wordmark Semplifica, the corporate
name Semplifica s.r.l., and the Semplifica logo shipped under
frontend/public/semplifica/ are
trademarks of Semplifica s.r.l. and are reserved
separately from the code license. The MikeRust name is also reserved
as the identifier of this upstream (MikeRust ships without its own logo
for now — only the Semplifica mark is present in the UI). Forks with
substantive changes are asked to drop the Semplifica wordmark/logo and
rename the binary; see NOTICE.md for the full policy and
the precedent (GitLab CE, Mastodon, Nextcloud, Element, Plausible, …).




