A local-first AI workspace for durable project memory, curated context, and inspectable computer work.
Archivist turns projects into persistent Collection workspaces. A Collection can bring together multiple Libraries, durable Chats, Agents, open files, and the exact desktop state needed for one task.
Instead of treating every AI session as disposable, Archivist preserves the working context around the conversation:
Choose a Collection
→ restore its tabs, layout, Chats, and active Library
→ browse code, documentation, assets, and research
→ retrieve or attach trusted evidence
→ work through a persistent Agent
→ inspect the exact context used
→ return later without reconstructing the session
Archivist is under active development. The native Qt/QML application in frontend/ is the product frontend. The retired Electron/React prototype is kept outside this repository as a historical reference.
- Collection workspaces — group multiple Libraries, Chats, and Agents into task-specific environments that can be switched without rebuilding the session.
- Persistent editor tabs — open files and Chats as first-class tabs, reorder them with polished drag-and-drop, restore their order and active state after restart, and reuse the same file identity and icon mapping as the Explorer.
- Embedded development workspace — edit source through Monaco, run persistent terminals through xterm.js, and keep navigation inside Archivist tabs.
- Workspace-scoped language support — supervise local language servers per project for TypeScript/JavaScript, React/Next, QML, C/C++, Rust, Python, Go, YAML, Bash, and Markdown.
- Built-in web and SQL tooling — use Monaco workers for HTML, CSS/SCSS/Less, and JSON, with SQL highlighting and completion isolated to SQL files.
- Archivist editor commands — own the editor command registry and context menu instead of depending on Monaco private APIs.
- Multi-Library Collections — attach separate code, documentation, asset, research, or design Libraries to the same Collection.
- Persistent Library trees — remember the selected Library, expanded folders, selected node, filter text, and scroll position independently for every Library.
- Git-aware Explorer — merge Library scans with repository status, decorate existing files and folders, mute ignored paths, summarize descendant changes on folders, and never resurrect deleted files as phantom tree rows.
- Shared native icon system — use locally vendored Codicons for controls, Streamline artwork for folders, and the actual VS Code Seti font for compact file icons across the Explorer and editor tabs.
- Local-first Libraries — register folders, scan their contents, and browse cataloged files without surrendering ownership of the filesystem.
- Safe native file preview — open supported text and source files through a root-constrained, read-only backend boundary.
- Deterministic text indexing — extract supported UTF-8 files, split them into stable chunks, preserve line provenance, and index them with SQLite FTS5.
- Incremental rescanning — reuse unchanged documents, replace changed chunks, remove stale records, and report failed or unavailable files honestly.
- Automatic Library retrieval — search the active Library for each normal Chat request and provide bounded, relevant excerpts without requiring manual attachments.
- Durable Chat — preserve conversations, selected state, Agent assignments, and large histories with cursor-based pagination.
- Explicit file attachments — attach specific Library files to an individual Chat when the user wants guaranteed evidence.
- Bounded context — budget recent history, automatic retrieval, and attached evidence through the selected Context Compiler without replacing the user's current intent.
- Durable Context Inspector — inspect the compiler, model, token accounting, warnings, message selection, retrieval mode, and source outcomes behind individual assistant responses.
- Reviewable AI edits — let model tools propose bounded Library file creation, full-content patches, directory creation, renames, and moves without writing immediately; persist the proposal, require human approval, fail closed on stale state, synchronize derived Library state after execution, and support guarded undo.
- Configurable Agents — create reusable AI identities and attach Agent rosters to conversations.
- Native management workflows — create, rename, archive, restore, duplicate, and delete Collections, Chats, and Agents through the Qt client.
- Provider abstraction — OpenAI is currently supported behind an adapter boundary so project continuity does not belong to one model vendor.
- Managed native development — build and run the backend and Qt desktop client from the repository root in one supervised terminal session.
Archivist is designed around a few simple rules:
- Local before cloud. User files and project continuity should remain under the user's control.
- Durable history, temporary provider context. Chats persist; only curated context is sent to a model.
- Evidence is not intent. Retrieved material must remain visibly distinct from the user's current request.
- Inspection before automation. A context system should explain what it used before it begins making broader decisions.
- Read-only before mutation. Inspection and retrieval come before file-writing or autonomous actions.
- Human approval before consequences. Important operations should be reviewable, attributable, and reversible.
- Providers are workers, not owners. Archivist owns memory, sources, permissions, artifacts, and continuity.
- Complexity must pay rent. Prefer small, complete vertical slices over speculative infrastructure.
Archivist separates durable project content from the local desktop state used to work with it:
Collection
├── Libraries
│ ├── codebase
│ ├── documentation
│ ├── assets
│ └── research
├── Chats
├── Agent roster and defaults
└── local workspace state
├── open file and Chat tabs
├── active tab
├── Explorer visibility and width
├── Chat dock mode and height
├── active Library
└── per-Library tree expansion, filter, selection, and scroll
Switching Collections should feel like switching complete task desktops. Worktrees, split editor groups, dockable panes, and multi-monitor layouts are planned extensions of this same boundary.
Archivist is a local modular monolith with clear domain boundaries:
Qt 6 / QML desktop
Collection workspaces, editor tabs, Explorer, Chat, previews, Context Inspector
|
C++ domain stores
HTTP requests, client state, QML-facing models
|
Express API
validation, orchestration, product behavior
|
Domain models and services
persistence, safe file access, context compilation
|
SQLite + filesystem + AI providers
durable state, authoritative files, retrieval, generation
The API owns business rules. QML owns presentation and interaction. C++ stores bridge the two without duplicating backend invariants.
current user message
+ recent durable conversation
+ automatically retrieved Library excerpts
+ explicitly attached Library evidence
→ Context Compiler
→ bounded provider request
→ assistant response
→ durable context-run snapshot
→ native Context Inspector
The current user message remains the highest-priority intent. Automatically retrieved and explicitly attached files are evidence, not instructions. Explicit attachments remain stronger than automatic candidates.
Each newly generated assistant response can preserve:
compiler ID and version
provider, model, and Agent
input budget and response reserve
estimated tokens used
included and omitted messages
compiler warnings and timing
source outcomes and token contributions
Source outcomes are explicit:
Included
Truncated
Omitted
Unavailable
Failed
Context records describe what happened during a specific response. They are not reconstructed later from files that may have changed.
Filesystem → authoritative user file contents
SQLite → Collections, Libraries, Chats, Agents, messages, attachments, context records, indexes
QSettings → local Collection, tab, layout, and Library-tree workspace state
Providers → temporary generation workers
Archivist → continuity, context, permissions, provenance, outcomes
Archivist/
├── assets/ README artwork and project media
├── backend/ Express 5, TypeScript, SQLite, AI and cognition domains
├── frontend/ Primary Qt 6 / QML desktop frontend
│ ├── qml/App/ Workbench, Explorer, Chat, previews, inspectors and editors
│ ├── qml/App/Icons/ Shared controls, file resolvers, generated Seti registry and licenses
│ ├── qml/App/Workbench/IdeHost/Web/
│ │ Embedded Monaco and xterm.js feature
│ └── src/App/Domains/ C++ Library, Chat and Agent stores
├── language-test-lab/ Small cross-language fixtures for editor smoke tests
├── scripts/ Native build, runtime, cleanup, smoke-test and context helpers
├── devHandoff.md Current development state and coding-chat handoff
└── README.md
The current development environment targets macOS.
- Node.js 24 LTS
- npm 10 or newer
- Qt 6.8 or newer
- CMake 3.24 or newer
- Ninja
Example macOS dependencies:
brew install qt cmake ninjaFrom the repository root:
nvm use
npm install
npm run lsp:install
cp backend/.env.example backend/.env
# Add the required AI-provider credentials to backend/.env.
npm run devThe root development command owns the complete native session:
validate Node and better-sqlite3
→ stop the previous managed backend
→ clean up stale Archivist listeners
→ start one backend
→ wait for API health
→ build the embedded IDE assets
→ build the Qt client
→ launch Archivist
→ clean up the backend when Archivist exits
The backend API runs at:
http://127.0.0.1:3333/api
Build the complete active application:
npm run buildBuild and launch the backend and native Qt client in one terminal:
npm run devStop a previous managed development session:
npm run dev:stopFocused native commands:
npm run dev:qt
npm run build:qt
npm run qt:configure
npm run qt:runRegenerate the locally vendored icon assets and Seti registry after changing the icon manifest or vendor script:
npm run icons:vendorThe generated assets live under frontend/qml/App/Icons/Assets/. Keep frontend/qml/App/Icons/THIRD_PARTY_ICONS.md synchronized with every vendored source.
Use the repository helpers to collect evidence before changing code when a failure is unclear.
Start a detached diagnostic session when Archivist must remain running while other commands inspect it:
./scripts/qt-dev-detached
./scripts/qt-dev-detached --follow
./scripts/qt-stopThe detached launcher writes bounded backend and frontend logs under
backend/data/runtime/logs/. Without --follow, it leaves Archivist running;
with --follow, it streams both logs and stops the managed session on exit.
Run focused diagnostics and audits with:
./scripts/diagnose-navigation
npm run diagnose:language-support
node scripts/diagnose-language-support.mjs --lines 1500
node scripts/diagnose-language-support.mjs --full
./scripts/qt-typography-audit
./scripts/qt-typography-audit --checkdiagnose-navigation writes navigation-diagnostic.txt at the repository root.
The language diagnostic includes Git and runtime state, tool availability, live
language-server configuration and sessions when the backend is running, client
events, fixtures, and recent logs. Use --lines for a larger log window or
--full for unfiltered tails. The typography audit reports current usage;
--check rejects regressions against the committed baseline.
Run focused backend verification with:
npm run build
node scripts/test-collections.mjs
node scripts/test-chat-agent-rosters.mjs
npm run test:library-index -- "a term you know exists"The Collection and Chat-Agent smoke tests use temporary databases. The Library index test expects Archivist's backend to be running and rescans the currently active Library before searching it.
Generate a fresh coding-chat context bundle with:
./scripts/qt-context
./scripts/qt-context backend/src/api/cognition frontend/qml/App/Files
./scripts/qt-context 12 backend/src/api/languageSupportWithout a number, the script creates the next available qt-context-NNN.txt.
An optional leading number selects the sequence, and each remaining argument adds
a focused file or directory. The bundle records Git state, recent commits, the
repository tree, relevant uncommitted diff, and included file contents while
skipping large and binary files. Upload the generated bundle instead of pasting
source files piecemeal.
Language-support commands:
npm run lsp:install
npm run lsp:doctor
npm run lsp:check
npm run check:language-support
npm run diagnose:language-support
npm run clean:language-test-lablsp:install synchronizes the exact npm-managed tool versions in
scripts/language-tools.json. Native tools such as qmlls, clangd,
rust-analyzer, gopls, and Marksman are discovered from PATH. Missing
optional native tools do not disable ordinary editing.
Set ARCHIVIST_LANGUAGE_SERVER_TRACE=1 before npm run dev when raw server
stderr is needed. Normal runs suppress known setup chatter while preserving
warnings, process exits, and diagnostic telemetry.
| Surface | Provider | Current scope |
|---|---|---|
| TypeScript, JavaScript, TSX, JSX | TypeScript language server | React/Next navigation, completion, diagnostics, references, rename, formatting, and code actions |
| QML | qmlls |
Workspace-aware completion, diagnostics, and navigation |
| C and C++ | clangd |
Best with compile_commands.json, compile_flags.txt, or CMake metadata |
| Rust | rust-analyzer |
Cargo workspace intelligence |
| Python | Pyright | Completion, navigation, and type diagnostics |
| Go | gopls |
Optional; available when the local Go toolchain provides it |
| YAML, Bash, Markdown | Language servers | Completion, diagnostics, and navigation where advertised |
| HTML, CSS, SCSS, Less, JSON | Monaco workers | Built-in validation, completion, hover, and formatting |
| SQL files | Monaco SQL provider | Syntax highlighting and isolated generic completion; no database-schema awareness yet |
Useful checks:
npm run lint
curl http://127.0.0.1:3333/api/health
sqlite3 backend/data/archivist.db "PRAGMA user_version;"
lsof -nP -iTCP:3333 -sTCP:LISTENThe managed backend PID is stored at:
backend/data/runtime/qt-dev-backend.pid
npm run dev owns the backend process tree and cleans it up when the Qt application exits or the terminal receives Ctrl+C.
When a previous session ended unexpectedly:
npm run dev:stop
npm run devThe cleanup script only stops backend processes belonging to this Archivist repository. It refuses to kill an unrelated application using port 3333 and reports the conflicting process instead.
better-sqlite3 is compiled for a specific Node ABI. After changing Node versions:
nvm use
npm rebuild better-sqlite3
npm run devA native-module mismatch commonly appears as:
ERR_DLOPEN_FAILED
The development launcher validates the active Node version and SQLite module before starting the application.
The backend also logs the active database path, schema version, and important table readiness during startup.
Archivist currently has:
native Qt Workbench
→ Collection-scoped task workspaces
→ draggable persistent file and Chat tabs with shared Seti file icons
→ multiple Libraries per Collection
→ Git-aware Explorer decorations without phantom deleted files
→ compact Collection and Library controls with native iconography
→ independently restored Library trees and scroll positions
→ durable Chats and Agent rosters
→ safe Library file preview
→ deterministic Library indexing and lexical retrieval
→ bounded attached and retrieved evidence
→ durable Context Inspector records
→ embedded Monaco and xterm.js development workspace
→ workspace-scoped language services with local diagnostics
→ one-command native development workflow
The current daily-driver loop is:
select a Collection
→ resume its exact workspace
→ switch among code, documentation, assets, or research Libraries
→ open files and Chats as tabs
→ ask through the assigned Agent
→ inspect the evidence and context used
The next product milestone is rich file rendering on top of the shared icon and file-identity system:
pleasant native Markdown reading
→ renderer selection by file type
→ images and structured data
→ PDFs, diffs, and richer asset previews
→ keep source files read-only until mutation workflows are explicit
Capability-driven editor commands such as Find References, Rename, Quick Fix, and formatting remain the next focused IDE slice after the renderer foundation.
Current deliberate limits:
- only one Library tree is displayed at a time, even when a Collection references several Libraries;
- automatic retrieval searches the active Library rather than every Library in the Collection;
- most files still use a plain text preview;
- the shared icon registry currently covers the Explorer, editor tabs, navigation controls, and terminal workbench; larger branded surfaces and preview-specific artwork remain future work;
- tabs and Library contents are not yet worktree-scoped;
- split editor groups and dockable panes are not implemented yet.
Persistent projects. Swappable workspaces. Curated context. Inspectable memory. Local ownership.
