First off, thanks for taking the time to contribute! DSCode is a community-driven project, and every contribution matters.
This project adheres to the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code.
- Node.js 20+ and npm
- Rust stable (1.75+) with cargo
- Platform dependencies:
- Linux:
libwebkit2gtk-4.1-dev,libssl-dev,libgtk-3-dev,librsvg2-dev,patchelf - macOS: Xcode Command Line Tools (
xcode-select --install) - Windows: Microsoft Visual C++ Build Tools
- Linux:
-
Clone the repository:
git clone https://github.com/dipankar/dscode.git cd dscode -
Install frontend dependencies:
npm install
-
Start development mode (hot reload):
npm run tauri:dev
DSCode uses a Cargo workspace with 8 members:
| Crate | Path | Purpose |
|---|---|---|
dscode-core |
crates/dscode-core/ |
TextBuffer, AppDirectories, shared types |
dscode-lsp |
crates/dscode-lsp/ |
LSP client, manager, connection pool |
dscode-dap |
crates/dscode-dap/ |
Debug Adapter Protocol client and pool |
dscode-extension-host |
crates/dscode-extension-host/ |
Extension host manager, IPC, sandbox, permissions |
dscode-terminal |
crates/dscode-terminal/ |
Terminal manager, PTY lifecycle |
dscode-session |
crates/dscode-session/ |
Session manager, extension lifecycle, workspace, config |
dscode |
src-tauri/ |
Tauri binary (depends on all library crates) |
monaco-wasm |
monaco-wasm/ |
Monaco Editor WASM bindings |
Each library crate can be built and tested independently:
# Build a specific crate
cargo build -p dscode-core
# Test a specific crate
cargo test -p dscode-lsp
# Check a specific crate
cargo check -p dscode-sessionSome crates have optional Tauri integration via feature flags:
dscode-extension-host—taurifeature enablesAppHandle-dependent IPCdscode-terminal—taurifeature enablesTauriEventSenderdscode-session—taurifeature enables Tauri IPC providers
The binary crate enables all Tauri features. Library crate tests run without Tauri features.
Run these checks before submitting a pull request:
# Full workspace type check
cargo check --workspace
# Full workspace tests
cargo test --workspace
# Clippy lint (treat warnings as errors)
cargo clippy --workspace -- -D warnings
# Format check
cargo fmt --check
# Frontend TypeScript check
npx tsc --noEmit
# Svelte component type check
npm run check
# Extension host TypeScript check
cd extension-host && npx tsc --noEmit
# Vite production build
npx vite build
# Full Tauri production build
npm run tauri:build
# Lint
npm run lintAll of the following must pass before committing:
cargo check --workspace— Rust workspace compilescargo test --workspace— All workspace tests passcargo clippy --workspace -- -D warnings— No clippy warningscargo fmt --check— Code is formattednpx tsc --noEmit— Frontend TypeScriptcd extension-host && npx tsc --noEmit— Extension host TypeScriptnpx vite build— Production build succeeds
- Format with
cargo fmt - Lint with
cargo clippy --workspace -- -D warnings - Use
tokio::sync::Mutex(neverstd::sync::Mutex) in async contexts - Use
tokio::task::spawn_blockingfor filesystem I/O in Tauri command handlers - Use
tracingmacros (info!,debug!,error!,warn!) instead ofprintln!/eprintln! - Use typed error enums (
thiserror) instead ofStringfor internal errors - Use
pub(crate)for items that shouldn't be part of the crate's public API - Document all
pubitems with///doc comments
- Format with Prettier:
npm run format - Lint with ESLint:
npm run lint - Type-check with
npm run check(svelte-check) - Use
showConfirmPrompt()/showAlertPrompt()fromstores/windowPromptinstead ofconfirm()/alert() - Components must unsubscribe from stores in
onDestroy()to prevent memory leaks - Add ARIA attributes for accessibility (
role,aria-label,aria-live) - Use focus traps for modal components
- CSS custom properties only (VS Code theme-compatible)
- No Tailwind
Use Conventional Commits format:
type(scope): description
[optional body]
Types: feat, fix, refactor, docs, test, chore, perf, ci, build
Examples:
feat(editor): add multi-cursor supportfix(terminal): resolve PTY close race conditionrefactor(session): extract workspace state into separate module
- Fork the repository and create a branch from
main - Make changes with clear, descriptive commits following conventional commits
- Run all pre-commit checks (listed above)
- Open a PR against
mainwith a clear description of the change - Ensure CI passes — all type checks, lints, and builds must succeed
- Address review feedback promptly
- One approval required for merge (may increase as the project grows)
Use the same conventional commit format: type(scope): description
DSCode has three main layers:
- Frontend: Svelte 4 + TypeScript + Monaco Editor + xterm.js
- Backend: Tauri 2.1 (Rust) with tokio async runtime
- 6 reusable library crates (dscode-core, dscode-lsp, dscode-dap, dscode-extension-host, dscode-terminal, dscode-session)
- 1 binary crate (src-tauri) that depends on the library crates
- Extension Host: Separate Node.js process communicating via NNG IPC
See docs/architecture/overview.md for the full architecture document and docs/ for additional design docs.
# All workspace tests
cargo test --workspace
# Specific crate tests
cargo test -p dscode-core
cargo test -p dscode-lsp
cargo test -p dscode-dap
cargo test -p dscode-extension-host
cargo test -p dscode-terminal
cargo test -p dscode-session
# Extension host tests
cd extension-host && npm test
# Svelte component type check
npm run checkAll workspace crates share the same version (currently 0.1.0).
- Version bump process: update
workspace.package.versionin the rootCargo.toml, then runnpm versionin each JS package to match. - Tag format:
v0.1.0 - Release cadence: bi-weekly patch releases, monthly minor releases during active development.
- Before release: ensure
cargo publish --dry-runpasses for every crate in the workspace.
Open an issue on GitHub or start a discussion.