This guide documents Chatbox (Community Edition) for administrators, architects, and developers: how it is built, how it stores and protects data, how its subsystems fit together, and how to deploy and operate every part of it (including the web build, mobile builds, and the team-sharing proxy). For end-user instructions, see the companion User Guide.
1. Executive Summary
What it is. Chatbox is a cross-platform AI chat client built on Electron. The same TypeScript/React codebase compiles to a desktop app (Windows, macOS, Linux), a web app, and mobile apps (iOS/Android via Capacitor). It connects to 20+ AI providers, stores all user data locally, and adds image generation, retrieval-augmented knowledge bases, web search, MCP tooling, and reusable "Copilot" assistants.
Architecture in one line. A standard three-process Electron layout
(main / preload / renderer) plus a shared layer, where the renderer is
the product (a React SPA routed by file-based TanStack Router) and the main
process provides OS integration, persistent storage, the knowledge-base
database, and MCP stdio transport. The same renderer runs in a browser (web
build) or a WebView (mobile build) behind platform abstractions.
Key technical facts every operator should know:
| Area | Fact |
|---|---|
| Runtime | Electron 26, React 18, TypeScript 5.8 |
| Build | pnpm + electron-vite (Vite 7) + electron-builder; Capacitor 7 for mobile |
| AI layer | Vercel AI SDK (ai, @ai-sdk/*) — one SDK, many providers |
| State | jotai + zustand + @tanstack/react-query |
| UI | Mantine + MUI + Tailwind, with a chatbox-* design-token system |
| Config store | electron-store JSON in userData, auto-backed-up every 10 min |
| Knowledge base | libSQL vector store via Mastra (@mastra/libsql, @mastra/rag) |
| Security posture | webSecurity: false; contextBridge exposes a generic invoke |
| Telemetry | Google Analytics 4 + Sentry + Plausible (all opt-out) |
| Updates | electron-updater, releases hosted on Cloudflare R2 |
| License | GPLv3 (Community Edition) |
Important
Chatbox is a client application, not a server. There is no backend to deploy for the app itself, no listening port, no multi-user mode, and no central database. The only deployable server component is the optional team-sharing proxy (§11). The "Chatbox AI" cloud service is a first-party SaaS the client can call, not part of this repo.
2. Architecture
2.1 Process model
Electron application
┌─────────────────────────────────────────────────────────────────┐
│ MAIN process (Node.js) src/main/ │
│ • BrowserWindow lifecycle, tray, global shortcuts, menu │
│ • electron-store config + auto-backup (store-node.ts) │
│ • auto-update (electron-updater) (app-updater.ts) │
│ • proxy, auto-launch, deep links, file parsing │
│ • Knowledge Base: libSQL DB + RAG worker (knowledge-base/) │
│ • MCP stdio transport (mcp/) │
│ ▲ │
│ │ ipcMain.handle(...) ◄── contextBridge "invoke" │
│ ▼ │
│ PRELOAD src/preload/index.ts │
│ • exposes window.electronAPI = { invoke, on* listeners } │
│ ▲ │
│ │ window.electronAPI │
│ ▼ │
│ RENDERER (Chromium) src/renderer/ ← THE PRODUCT │
│ • React 18 SPA, TanStack file-based router │
│ • jotai/zustand stores, react-query │
│ • Vercel AI SDK calls go straight to provider APIs │
└─────────────────────────────────────────────────────────────────┘
SHARED src/shared/ — types, defaults, provider registry, model
classes, errors; imported by every process.
The four source roots:
| Root | Role |
|---|---|
src/main |
Electron main process (Node). OS integration + KB DB + MCP. |
src/preload |
The contextBridge shim — the only renderer→main door. |
src/renderer |
The React application — UI, routing, stores, model calls. |
src/shared |
Cross-process code: types, defaults, provider/model registry, errors, file-extension tables. |
Note
Unusually for an Electron app, the renderer talks to AI providers directly over HTTP using the Vercel AI SDK — model traffic does not flow through the main process. The main process is used for OS-level work, the config store, the knowledge-base database, and launching stdio MCP servers. This is why
webSecurityis disabled (see §9).
2.2 The renderer route tree = the feature map
Chatbox uses file-based routing (@tanstack/react-router); the generated
src/renderer/routeTree.gen.ts is the authoritative page list. The top-level
routes are the app's features:
| Route | Feature |
|---|---|
/ |
Home / new conversation (model selector, Copilot picker, input box) |
/session/$ |
A chat or picture conversation |
/copilots |
Copilot gallery & management |
/image-creator |
Image generation workspace |
/guide |
First-run onboarding |
/about |
About / links / version |
/settings/* |
Settings panels (see below) |
/dev, /task |
Developer/internal pages |
Settings sub-routes (src/renderer/routes/settings/), which double as the config
surface:
chatbox-ai, provider (+ provider/$providerId), default-models,
web-search, mcp, knowledge-base, document-parser, chat, hotkeys,
general. The mcp and knowledge-base panels are gated behind
featureFlags in src/renderer/utils/feature-flags.ts.
2.3 State management
jotaiatoms (src/renderer/stores/atoms/) for fine-grained reactive state (current session id, remote config, etc.), withjotai-immer/optics.zustandstores (settingsStore,uiStore,authInfoStore,onboardingStore,chatStore/sessionActions) for app/settings/UI state.@tanstack/react-queryfor async/server data (model registry, remote copilots, blobs).
Settings and onboarding stores hydrate from persistent storage on boot
(initSettingsStore(), initOnboardingStore() in routes/__root.tsx).
2.4 Platform abstraction
src/renderer/platform/ abstracts everything platform-specific behind one
interface so the same renderer runs on desktop, web, and mobile. Concrete
implementations include DesktopFileStorage, LocalStorage, SQLiteStorage,
MobileSQLiteStorage, IndexedDBStorage, plus exporters and loggers
(web_platform.ts, desktop_platform.ts, test_platform.ts). Build-time
flags (CHATBOX_BUILD_PLATFORM, CHATBOX_BUILD_TARGET) select the
implementation; platform.type is 'desktop' | 'web' | 'mobile'.
3. Requirements
3.1 Runtime (end users)
| Platform | Requirement |
|---|---|
| Windows | Windows 10/11, x64 or ARM64 |
| macOS | Intel or Apple Silicon (universal builds: arm64 + x64) |
| Linux | AppImage or .deb, x64 or ARM64 |
| Web | Any modern Chromium/Firefox/Safari browser |
| Mobile | iOS (App Store) / Android (Play or APK) |
3.2 Build (developers)
| Tool | Version (from package.json engines) |
|---|---|
| Node.js | >=20.0.0 <23.0.0 |
| pnpm | >=10.17.0 (pinned packageManager: pnpm@10.33.0) |
| Electron | ^26.6.10 |
| TypeScript | ^5.8.3 |
| Capacitor (mobile) | ^7.0.0 |
Note
The pnpm workspace enforces supply-chain hygiene:
pnpm-workspace.yamlsetsminimumReleaseAge: 10080(10080 minutes = 7 days), so only packages published at least a week ago are installed.
4. Build & Distribution
4.1 Build commands
All builds go through electron-vite (config: electron.vite.config.ts), which
compiles the three targets (main, preload, renderer).
| Command | Purpose |
|---|---|
pnpm dev (pnpm start) |
Run in development (electron-vite dev) |
pnpm dev:web |
Renderer-only web dev (DEV_WEB_ONLY=true) |
pnpm build |
Build all three targets |
pnpm build:web |
Web build (CHATBOX_BUILD_PLATFORM=web) + strip sourcemaps |
pnpm package |
Build + electron-builder installer for current OS |
pnpm package:all |
Build installers for Windows + macOS + Linux |
pnpm mobile:ios / mobile:android |
Build + cap sync + open native IDE |
pnpm test |
vitest run |
pnpm lint / format / check |
Biome lint / Biome format / tsc --noEmit |
Build flavor is driven by environment variables consumed in
electron.vite.config.ts:
| Variable | Effect |
|---|---|
CHATBOX_BUILD_PLATFORM |
web / ios / android / unset (desktop) |
CHATBOX_BUILD_TARGET |
mobile_app for Capacitor builds |
CHATBOX_BUILD_CHANNEL |
e.g. google_play (affects store-review behavior) |
USE_LOCAL_API / USE_BETA_API |
Point at local/beta Chatbox AI backend |
USE_LOCAL_CHATBOX / USE_BETA_CHATBOX |
Point at local/beta web endpoints |
SENTRY_AUTH_TOKEN / SENTRY_RELEASE / SENTRY_DIST |
Enable Sentry sourcemap upload |
DEV_PORT |
Renderer dev server port (default 1212) |
The renderer build splits vendor chunks (vendor-ai for ai/@ai-sdk,
vendor-ui for Mantine/Tabler, vendor-charts for mermaid/d3) to control
bundle size and build memory.
4.2 Packaging matrix (electron-builder.yml)
| Target | Arch | Output | Signing |
|---|---|---|---|
| Windows | x64, arm64 | NSIS installer (${productName}-${version}-Setup.exe) |
custom_win_sign.js, SHA-256 |
| macOS | arm64, x64 | DMG (distribution) | hardened runtime + entitlements; notarize via afterSign hook (notarize.js) |
| Linux | x64, arm64 | AppImage + .deb |
— |
appId:xyz.chatboxapp.app;productName:Chatbox.- ASAR packaging is on; native bits are unpacked (
**/*.{node,dll}and the wholenode_modules/libsql/**). AnafterPackhook (patch-libsql.cjs) patches libSQL for packaged builds. - Releases are published to Cloudflare R2 (S3-compatible) under
bucket: chatbox,path: /releases, with the channel set by theUPDATE_CHANNELenv var.
4.3 Auto-update
src/main/app-updater.ts wires electron-updater:
- On launch (if Automatic updates is on) it checks immediately, then every hour.
- It tries a list of mirror feed URLs in order until one responds:
chatboxai.app,api.chatboxai.app,api.ai-chatbox.com,api.chatboxapp.xyz,api.chatboxai.com(each at/api/auto_upgrade). - If Beta updates is enabled, it switches to the
betachannel and disables downgrades. - When an update is downloaded, the renderer is notified (
update-downloaded) and the user can apply it via theinstall-updateIPC call (autoUpdater.quitAndInstall()).
Note
AppImage and app-store builds typically rely on external updaters; for those, direct users to GitHub Releases.
5. Configuration & Data Storage
5.1 Where data lives
Everything is under Electron's userData directory (e.g.
%APPDATA%\Chatbox on Windows, ~/Library/Application Support/Chatbox on
macOS, ~/.config/Chatbox on Linux):
| Path | Contents |
|---|---|
config.json |
electron-store data: settings, configs (incl. uuid), configVersion |
config-backup-<ISO>.json |
Rolling auto-backups (every 10 min) |
databases/chatbox_kb.db |
libSQL knowledge-base DB + vector index |
| log file (electron-log default) | Diagnostic logs |
Browser (web) and mobile builds use IndexedDB / SQLite via the platform
abstraction instead of config.json.
5.2 The config store and its self-healing
src/main/store-node.ts is the durability core:
- On startup it validates
config.json. If invalid, it walks the newest backup files and restores the latest valid one. electron-storeis created withclearInvalidConfig: true.autoBackup()runs every 10 minutes (and re-arms on power resume / pauses on suspend), keeping recent valid backups and pruning old ones.- Large binary values (avatars, background images, generated images) are stored
as blobs via separate IPC (
getStoreBlob/setStoreBlob/...), not insideconfig.json.
5.3 Settings schema (defaults)
src/shared/defaults.ts defines the authoritative defaults. Notable values:
| Key | Default |
|---|---|
theme |
System |
spellCheck |
true |
enableMarkdownRendering / LaTeX / Mermaid |
true |
autoPreviewArtifacts |
false |
pasteLongTextAsAFile |
true |
autoCompaction |
true |
autoLaunch |
false |
allowReportingAndTracking |
true (opt-out) |
| default chat session | provider chatbox-ai, model chatboxai-4, unlimited context |
| default picture session | provider chatbox-ai, model DALL-E-3, vivid, 1 image |
| web search | provider build-in (Chatbox AI) |
| document parser | unset → desktop defaults to local, mobile/web to chatbox-ai |
Default shortcuts (settings.shortcuts): quick toggle Alt+\``, focus input mod+i, web-browsing mod+e, new chat mod+n, new picture mod+shift+n, session nav mod+tab/mod+shift+tab, refresh context mod+r, search mod+k, send Enter, send-without-reply Ctrl+Enter`.
5.4 Environment variables
There is no .env-style runtime config for end users. The environment
variables in §4.1 are build-time flags. Runtime
behavior toggles that do exist are minimal:
| Variable | Used by | Effect |
|---|---|---|
NODE_ENV |
main/renderer | development enables debug menus & devtools |
DEBUG_PROD |
main | Force debug behavior in a production build |
START_MINIMIZED |
main | Start the window minimized |
COMPUTERNAME |
main | Windows device-name source |
Important
Negative knowledge — things that do NOT exist: no system-wide config file (no
/etc/chatbox/, no registry policy keys), no HTTP API exposed by the app, no webhooks, no plugin system with arbitrary code (extensibility is via MCP), and no telemetry that includes message content. Don't document or configure knobs that aren't here.
5.5 Import / export & migration
src/renderer/routes/settings/general.tsx implements streaming JSON export of
selected data (Settings, Conversations, My Copilots, optionally
API KEY & License). When keys are not included, the exporter strips
apiKey/accessKey/secretKey/sessionToken/licenseKey/licenseDetail.
Import runs migrateOnData() (see stores/migration.ts) to upgrade older
exports, then relaunches the app. Schema evolution is tracked by
configVersion.
6. Provider & Model Architecture
6.1 Provider registry
Providers are registered into a Map via side-effect imports in
src/shared/providers/index.ts (import order determines UI order, with Chatbox
AI first). The registry API (src/shared/providers/registry.ts):
defineProvider, getProviderDefinition, getAllProviders,
getSystemProviders, hasProvider.
Each ProviderDefinition carries: id, name, type
(ModelProviderType: OpenAI | Claude | Gemini | OpenAIResponses),
urls, defaultSettings (apiHost/apiPath/models), an optional
modelsDevProviderId (for models.dev enrichment),
curatedModelIds, and a createModel() factory.
Built-in providers (22): chatbox-ai, openai, openai-responses,
gemini, claude, deepseek, qwen, qwen-portal, minimax, moonshot,
siliconflow, openrouter, ollama, lmstudio, azure, groq, xai,
mistral-ai, perplexity, volcengine, chatglm, github-copilot,
bedrock.
6.2 Model instantiation
getModel(settings, globalSettings, config, dependencies)
(src/shared/providers/index.ts) resolves the provider definition and calls its
createModel(). For custom providers, createCustomProviderModel()
(utils.ts) instantiates one of CustomOpenAI, CustomClaude, CustomGemini,
or CustomOpenAIResponses based on the chosen API type. Model metadata
(capabilities like vision / tool_use / reasoning, context window, max
output) is enriched from the model registry (src/shared/model-registry,
which snapshots models.dev data in snapshot.generated.ts).
API host/path normalization helpers (src/shared/utils) keep endpoints
consistent: normalizeOpenAIApiHostAndPath, normalizeClaudeHost,
normalizeGeminiHost, normalizeAzureEndpoint, normalizeOpenAIResponsesHostAndPath.
6.3 The AI call layer
The actual chat/stream/tool-call logic uses the Vercel AI SDK (ai +
@ai-sdk/*) under src/renderer/packages/model-calls, model-context,
context-management, token-estimation, tools, and web-search. Model
abstractions and the error hierarchy live in src/shared/models
(abstract-ai-sdk.ts, errors.ts).
6.4 OAuth
Some providers support OAuth (src/shared/oauth); when an OAuth token is active,
the provider's default API host is used and resolveEffectiveApiKey() resolves
the credential. Provider import/OAuth deep links arrive via
chatbox://provider/import.
7. Knowledge Base (RAG) Internals
Implemented entirely in the main process under src/main/knowledge-base/.
7.1 Storage
-
libSQL file DB at
userData/databases/chatbox_kb.db, accessed through Mastra'sLibSQLVector(@mastra/libsql). The same client serves both relational tables and the vector index (a single client to avoid corruption). -
Schema:
knowledge_base(id, name, embedding_model, rerank_model, vision_model, document_parser, provider_mode, created_at) kb_file(id, kb_id, filename, filepath, mime_type, file_size, chunk_count, total_chunks, status, error, parser_type, use_remote_parsing, parsed_remotely, processing_started_at, created_at)Schema upgrades are applied as idempotent
ALTER TABLE ... ADD COLUMNstatements (errors ignored when the column already exists). -
Vector index per KB is named
kb_{kbId}.
7.2 Ingestion pipeline
A background worker loop (startWorkerLoop) polls every 3 s for
pending files and processes them:
- Parse via the parser router (
parsers/):local,chatbox-ai(cloud), ormineru. The effective parser comes from the KB'sdocument_parserconfig (or a forcedchatbox-aiwhen the user retried "with server parsing"). - Chunk with Mastra
MDocument— strategyrecursive, size 512, overlap 50. - Embed in batches of 50 via
embedMany(AI SDK) using the KB's embedding model. - Upsert vectors with metadata (
text,fileId,filename,chunkIndex) into the libSQL vector index. - Track progress in
chunk_count/total_chunksso processing is resumable from the last completed chunk.
File state machine: pending → processing → done | failed | paused. Files
processing for > 5 min are marked failed (timeout); interrupted files left in
processing are reset to paused on next launch (manual resume). Per-file
limit is 100 MB (server parser limit is 50 MB).
7.3 Retrieval
searchKnowledgeBase(kbId, query) embeds the query, runs a vector
query({ topK: 20 }), then — if a rerank model is configured —
rerank(..., { topK: 5 }) to return the best passages. Failures fall back to the
raw vector results.
7.4 IPC surface
The KB exposes a clean IPC API (ipc-handlers.ts), all input-validated:
kb:list, kb:create, kb:update, kb:delete, kb:file:list,
kb:file:count, kb:file:list-paginated, kb:file:get-metas,
kb:file:read-chunks, kb:file:upload, kb:search, kb:file:retry,
kb:file:pause, kb:file:resume, kb:file:delete. Deletes run in a transaction
that removes rows and the vector index together.
Tip
The KB system reports failures to Sentry with rich tags (component, operation, kbId, filename). When diagnosing ingestion problems, the
operationtag (file_parsing,document_chunking,generate_embeddings,vector_storage,image_ocr_processing) tells you exactly which stage failed.
8. MCP (Model Context Protocol)
Chatbox is an MCP host built on @modelcontextprotocol/sdk and
@ai-sdk/mcp.
- Main process (
src/main/mcp/) provides the stdio transport (ipc-stdio-transport): it spawns local MCP server processes and bridges their events to the renderer over channels namedmcp:stdio-transport:{transportId}:{event}(the preload registers listeners viaaddMcpStdioTransportEventListener). All transports are closed onwill-quit. - Renderer (
src/renderer/packages/mcp/) manages server configs and tool invocation; Settings → MCP has built-in and custom server sections. Custom servers may be stdio (desktop) or remote (HTTP/SSE). - Config persists in
settings.mcp = { servers, enabledBuiltinServers }. - Install-by-link:
chatbox://mcp/install?server=<base64>opens the MCP settings pre-filled.
Caution
A stdio MCP server is an arbitrary local executable run with the user's privileges. In managed deployments, treat the MCP server list as a code-allowlist and review configurations distributed via
chatbox://deep links before approving them.
9. Security Analysis
Chatbox follows a client-trusts-itself model. Document it honestly rather than expecting a hardened sandbox.
9.1 Renderer security posture
From src/main/main.ts createWindow():
webSecurity: false— disabled on purpose so the renderer can call arbitrary provider APIs cross-origin (the AI SDK runs in the renderer). This is the central trade-off: it removes the browser's same-origin protection for the app's web content.allowRunningInsecureContent: false.contextBridge.exposeInMainWorld('electronAPI', { invoke, ...listeners })— the preload exposes a genericipcRenderer.invoke, so the renderer can call any IPC channel. There is no per-channel allowlist orvalidateSendercheck.- External links are opened in the system browser (
setWindowOpenHandler→shell.openExternal,action: 'deny'), preventing in-app navigation to remote origins. - Single-instance lock (
requestSingleInstanceLock) routes second-launch deep links to the existing window.
Warning
Because
webSecurityis off andinvokeis generic, the renderer is a trust boundary: any code running in it (including content rendered from model output) executes with the app's privileges. Mitigations in place are loading only local app content, denying new-window navigation, and not enabling@electron/remote. Operators distributing Chatbox should rely on code signing (Windows custom signer, macOS hardened runtime + notarization) to guarantee binary integrity.
9.2 Credentials & secrets
- API keys, license keys, and cloud tokens are stored in
config.json(local, unencrypted) and in blob storage for binary assets. They never leave the device except to the provider you call. - Exports strip secrets by default unless the user explicitly includes "API KEY & License" (§5.5).
9.3 Telemetry & privacy
Three optional analytics paths exist; all are governed by
allowReportingAndTracking (Settings → General → Error Reporting):
| System | Where | Data |
|---|---|---|
| Google Analytics 4 | src/main/analystic-node.ts (Measurement Protocol) |
App/version/platform events keyed by the install uuid |
| Sentry | @sentry/node (main) + @sentry/react (renderer) |
Crash/exception reports with operation tags |
| Plausible | web build (data-domain swapped to web.chatboxai.app) |
Page analytics |
Note
Telemetry is opt-out (
allowReportingAndTrackingdefaults totrue) and is described to users as "anonymous error data and events." Message content is not part of these payloads. For privacy-sensitive deployments, instruct users to disable it, or build with telemetry tokens unset.
9.4 Network
- A user-configurable proxy (
socks5://...etc.) is applied to the whole Electron session (src/main/proxy.ts,session.setProxy). - A per-provider "Improve Network Compatibility" (
useProxy) flag exists for hosts that need it (note the known mobile gap for custom Anthropic hosts, issue #3739).
10. Operations
10.1 Logs
electron-log writes to the platform default log path. Users can Export Logs
(Settings → General → Diagnostic Logs); the renderer calls the exportLogs /
clearLogs IPC handlers. The renderer can also push structured log lines into
the main log via appLog.
10.2 Backups
The config auto-backup (§5.2) is the
primary safety net. For full portability use the JSON export/import. The
knowledge-base DB (databases/chatbox_kb.db) is not included in the JSON
export — back it up at the filesystem level if KB contents are critical.
10.3 Deep-link & instance handling
The app registers the chatbox:// scheme (dev: chatbox-dev://) and handles:
chatbox://mcp/install, chatbox://provider/import, and an auth callback.
Deep links arriving via second-instance launch (Windows/Linux) or open-url
(macOS) are routed to the renderer with navigate-to.
10.4 OS integration toggles
Tray icon (show/hide + quit), global show/hide hotkey, launch at startup
(auto-launch), window-state persistence (size/position/maximized/fullscreen),
and native theme sync are all managed in the main process.
11. Team-Sharing Deployment
team-sharing/ ships a small reverse-proxy so a team can share one upstream
OpenAI-style API key without handing out the secret. It is a Caddy server:
team-sharing/main.shsubstitutes<HOST>and<KEY>into aCaddyfiletemplate and runscaddy run.- Configure via environment:
HOST(defaults to:80) andKEY(the shared access key). - Deploy it (Docker/host) somewhere your team can reach, then each member sets
their provider's API Host to the proxy URL and authenticates with the
shared
KEY.
See team-sharing/README.md in the repo for the exact Caddyfile and Docker
instructions.
Important
The proxy holds the real upstream API key. Run it over HTTPS, restrict network access to your team, and rotate
KEYperiodically. This is the only network-listening component associated with Chatbox.
12. Repository Structure
chatbox/
├── src/
│ ├── main/ Electron main process
│ │ ├── main.ts Window/tray/shortcuts/IPC entry
│ │ ├── store-node.ts electron-store + auto-backup
│ │ ├── app-updater.ts electron-updater
│ │ ├── proxy.ts, autoLauncher.ts, deeplinks.ts, file-parser.ts
│ │ ├── knowledge-base/ libSQL DB + RAG worker + IPC
│ │ ├── mcp/ stdio transport
│ │ └── adapters/ sentry, etc.
│ ├── preload/index.ts contextBridge shim
│ ├── renderer/ React SPA (THE PRODUCT)
│ │ ├── routes/ TanStack file-based routes (feature map)
│ │ ├── packages/ model-calls, mcp, web-search, tools, token-estimation, …
│ │ ├── platform/ desktop/web/mobile storage & exporters
│ │ ├── stores/ jotai atoms + zustand stores
│ │ ├── components/, modals/, i18n/
│ │ └── routeTree.gen.ts (generated)
│ └── shared/ types, defaults, providers/, models/, model-registry/, oauth/
├── team-sharing/ Caddy proxy for shared API keys
├── electron.vite.config.ts 3-target build config
├── electron-builder.yml packaging/signing/publish (R2)
├── biome.json lint + format
├── tailwind.config.js, postcss.config.js
└── package.json
13. Code Quality & Conventions
- Tooling: Biome 2.0 (
biome.json) for lint + format — single quotes, no semicolons, 2-space indent, 120-col width. (A legacy.eslintrc.jsremains.) Type-check withpnpm check(tsc --noEmit). - Testing:
vitest(node env) for unit tests (*.test.tsnext to sources) and integration tests undertest/integration(test:integration,test:file-conversation,test:model-provider). MSW (msw) mocks HTTP. - Path aliases:
@→src/renderer,@shared→src/shared. - Patches:
patches/carries pnpm patches forlibsql,mdast-util-gfm-autolink-literal, and@ai-sdk/deepseek; some deps are version- pinned viapnpm.overrides. - Pre-commit: Husky + lint-staged run Biome format on staged JS/TS.
14. Potential Improvements
These are observations from the source, not defects:
- Tighten the IPC boundary. The preload exposes a generic
invoke; moving to an explicit per-channel API (and addingvalidateSender) would shrink the renderer's trust surface (§9.1). - Re-evaluate
webSecurity: false. Where provider calls could be proxied through the main process, re-enabling web security would restore same-origin protections for the app shell. - Include the KB database in backups. The JSON export covers settings, chats,
and copilots but not
chatbox_kb.db; an integrated KB export/import would make migrations complete. - Encrypt secrets at rest. API/license keys sit in plaintext
config.json; OS keychain integration (orsafeStorage) would harden stored credentials. - Surface MCP/remote-transport errors more clearly. Several open issues (#3725, #3728) point to confusing failures for remote/HTTPS MCP servers.
15. Quick Reference
Build: pnpm install && pnpm dev · package: pnpm package /
pnpm package:all · web: pnpm build:web · mobile: pnpm mobile:ios|android.
Key paths (userData): config.json, config-backup-*.json,
databases/chatbox_kb.db, electron-log file.
Source roots: src/main (Node) · src/preload (bridge) · src/renderer
(SPA) · src/shared (types/providers/models).
Providers (22): chatbox-ai, openai, openai-responses, gemini, claude, deepseek, qwen, qwen-portal, minimax, moonshot, siliconflow, openrouter, ollama, lmstudio, azure, groq, xai, mistral-ai, perplexity, volcengine, chatglm, github-copilot, bedrock (+ custom OpenAI/Claude/Gemini/Responses).
KB pipeline: parse (local/chatbox-ai/mineru) → chunk (recursive 512/50) → embed (batch 50) → libSQL vector upsert → query topK 20 → rerank topK 5.
Security flags: webSecurity:false, generic invoke via contextBridge,
telemetry opt-out (allowReportingAndTracking), session-wide proxy support.
Distribution: electron-builder → NSIS / DMG / AppImage+deb (x64+arm64),
published to Cloudflare R2; electron-updater with hourly mirror-feed checks.