We love your input! We want to make contributing to DeepChat as easy and transparent as possible, whether it's:
- Reporting a bug
- Discussing the current state of the code
- Submitting a fix
- Proposing new features
- Becoming a maintainer
We use GitHub to host code, to track issues and feature requests, as well as accept pull requests.
- Develop directly on the
devbranch - Code submitted to the
devbranch must ensure:- Basic functionality works
- No compilation errors
- Project can start normally with
pnpm run dev
- Create a new feature branch named
feature/featurename - Merge the feature branch back to
devbranch upon completion
- Fork this repository to your personal account
- Create your development branch from
dev - Develop in your forked repository
- Submit a Pull Request to the
devbranch of the original repository - Describe the Issues fixed in your PR description (if applicable)
-
Clone the repository:
git clone https://github.com/ThinkInAIXYZ/deepchat.git cd deepchat -
Install required development tools:
- Install Node.js (Latest LTS version recommended)
-
Additional setup based on your operating system:
Windows:
- Install Windows Build Tools:
GUI Installation:
- Install Visual Studio Community
- Select "Desktop development with C++" workload during installation
- Ensure "Windows 10/11 SDK" and "MSVC v143 build tools" components are selected(Vistual Studio 2022 recommended)
- Install Git for Windows
macOS:
- Install Xcode Command Line Tools:
xcode-select --install
- Recommended: Install Homebrew package manager:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Linux:
- Install required build dependencies:
# Ubuntu/Debian sudo apt-get install build-essential git # Fedora sudo dnf groupinstall "Development Tools" sudo dnf install git
- Install Windows Build Tools:
GUI Installation:
-
Install project dependencies:
pnpm install pnpm run installRuntime
-
Start the development server:
pnpm run dev
src/main/: Electron main process. Presenters live here (window/tab/thread/config/llmProvider/mcp/config/knowledge/sync/floating button/deeplink/OAuth, etc.).src/preload/: Context-isolated IPC bridge; only exposes whitelisted APIs to the renderer.src/renderer/: Vue 3 + Pinia app. App code undersrc/renderer/src(components, stores, views, lib, i18n). Shell UI lives insrc/renderer/shell/.src/shared/: Shared types/utilities and presenter contracts used by both processes.runtime/: Bundled runtimes used by MCP and agent tooling (Node/uv).scripts/,resources/: Build, packaging, and asset pipelines.build/,out/,dist/: Build outputs (do not edit manually).docs/: Design docs and guides.test/: Vitest suites for main/renderer.
- Presenter pattern: All system capabilities are in main-process presenters; the renderer calls them via the typed
usePresenterhook and preload bridge. - Multi-window + multi-tab shell: WindowPresenter and TabPresenter manage true Electron windows/BrowserViews with detach/move support; an EventBus fans out cross-process events.
- Clear data boundaries: Chat data lives in SQLite (
app_db/chat.db), settings in Electron Store, knowledge bases in DuckDB, and backups via SyncPresenter. Renderer never touches the filesystem directly. - Tooling-first runtime: LLMProviderPresenter handles streaming, rate limits, and provider instances (cloud/local/ACP agent). MCPPresenter boots MCP servers, router marketplace, and in-memory tools with a bundled Node runtime.
- Safety & resilience: contextIsolation is on; file access is gated behind presenters (e.g., ACP workdir registration); backup/import pipelines validate inputs; rate-limit guards prevent provider overload.
┌─────────────────────────────────────────────────────────────┐
│ Electron Main (TS) │
│ Presenters: window/tab/thread/config/llm/mcp/knowledge/ │
│ sync/oauth/deeplink/floating button │
│ Storage: SQLite chat.db, ElectronStore settings, backups │
└───────────────┬─────────────────────────────────────────────┘
│ IPC (contextBridge + EventBus)
┌───────────────▼─────────────────────────────────────────────┐
│ Preload (strict API) │
└───────────────┬─────────────────────────────────────────────┘
│ Typed presenters via `usePresenter`
┌───────────────▼─────────────────────────────────────────────┐
│ Renderer (Vue 3 + Pinia + Tailwind + shadcn/ui) │
│ Shell UI, chat flow, ACP workspace, MCP console, settings │
└───────────────┬─────────────────────────────────────────────┘
│
┌───────────────▼─────────────────────────────────────────────┐
│ Runtime add-ons: MCP Node runtime, Ollama controls, ACP │
│ agent processes, DuckDB knowledge, sync backups │
└─────────────────────────────────────────────────────────────┘
- LLM pipeline:
LLMProviderPresenterorchestrates providers with rate-limit guards, per-provider instances, model discovery, ModelScope sync, custom model import, Ollama lifecycle, embeddings, and the agent loop (tool calls, streaming states). Session persistence for ACP agents lives inAcpSessionPersistence. - MCP stack:
McpPresenteruses ServerManager/ToolManager/McpRouterManager to start/stop servers, choose npm registries, auto-start default/builtin servers, and surface tools/prompts/resources. Supports StreamableHTTP/SSE/Stdio transports and a debugging UI. - ACP (Agent Client Protocol): ACP providers spawn agent processes, map notifications into chat blocks, and feed the ACP Workspace (plan panel with incremental updates, terminal output, and a guarded file tree that requires
registerWorkdir). PlanStateManager deduplicates plan items and keeps recent completions. - Knowledge & search: Built-in knowledge bases use DuckDB/vector pipelines with text splitters and MCP-backed configs; search assistants auto-select models and support API + simulated-browser engines via MCP or custom templates.
- Shell & UX: Multi-window/multi-tab navigation, floating chat window, deeplink handling, sync/backup/restore (SQLite + configs zipped with manifest), notifications, and upgrade channel selection.
- Use presenters, not Node APIs in the renderer: All OS/network/filesystem work should go through the preload bridge and presenters. Keep features multi-window-safe by scoping state to
tabId/windowId. - i18n everywhere: All user-visible strings belong in
src/renderer/src/i18n; avoid hardcoded text in components. - State & UI: Favor Pinia stores and composition utilities; keep components stateless where possible and compatible with detached tabs. Consider artifacts, variants, and streaming states when touching chat flows.
- LLM/MCP/ACP changes: Respect rate limits; clean up active streams before switching providers; emit events via
eventBus. For MCP, persist changes throughconfigPresenterand surface server start/stop events. For ACP, always callregisterWorkdirbefore reading the filesystem and clear plan/workspace state when sessions end. - Data & persistence: Use
sqlitePresenterfor conversation data,configPresenterfor settings/providers, andsyncPresenterfor backup/import. Do not write directly intoappDatafrom the renderer. - Testing & quality gates: Before sending a PR, run
pnpm run format,pnpm run lint,pnpm run typecheck, and relevantpnpm test*suites. Usepnpm run i18nto validate locale keys when adding strings.
- TypeScript + Vue 3 Composition API + Pinia; Tailwind + shadcn/ui for styling.
- Prettier enforces single quotes and no semicolons;
pnpm run formatbefore committing. - OxLint is used for linting (
pnpm run lint). Type checking viapnpm run typecheck(node + web targets). - Tests use Vitest (
test/main,test/renderer). Name tests*.test.ts/*.spec.ts. - Follow naming conventions: PascalCase components/types, camelCase variables/functions, SCREAMING_SNAKE_CASE constants.
- Keep PRs focused; describe what changed and which issues are addressed.
- Include screenshots/GIFs for UI changes and note any docs updates (README/CONTRIBUTING/docs).
- Verify format + lint + typecheck + relevant tests locally; note anything not run.
- Target the
devbranch; external contributors should fork-first and open PRs againstdev. - At least one maintainer approval is required before merge.
Feel free to open an issue with the tag "question" if you have any questions about contributing.
By contributing, you agree that your contributions will be licensed under the project's license.