edytlab

Developer Guide

Build edytlab from source, run tests, and contribute new tools or providers.

Prerequisites

ToolVersionNotes
Rust1.90 (auto-installed)Pinned via rust-toolchain.toml
Node.js22.22.2+CI uses 24
pnpm10.34+npm install -g pnpm

Platform extras

macOS: xcode-select --install for Xcode Command Line Tools.

Windows: Visual C++ Build Tools (Desktop development with C++) + WebView2. Install via Visual Studio Build Tools.

Linux (Ubuntu 22.04+):

sudo apt-get install -y \
  libgtk-3-dev libwebkit2gtk-4.1-dev \
  libayatana-appindicator3-dev librsvg2-dev \
  libssl-dev libasound2-dev libdbus-1-dev pkg-config patchelf

Initial setup

git clone https://github.com/laadtushar/edytlab.git
cd edytlab
pnpm install
cargo build --workspace    # first build: 5–20 min
pnpm tauri:dev             # dev mode; incremental builds take under 30 s

Project structure

apps/
  desktop/            Tauri shell — React frontend + Rust bridge
  cli/                Headless one-turn agent driver (E2E tests)
crates/
  ai/                 LLM providers, agent loop, keychain
  tools/              113 audio-editing tools
  session/            Session DAG data model and store
  audio-decoder/      File decode (symphonia)
  audio-dsp/          Sample-level DSP shared by tools and render
  audio-engine/       DSP graph and render
  audio-time/         Time-stretch and pitch-shift
  audio-analysis/     BPM, key, beat grid
  recorder/           Microphone capture to WAV; recording-latency measurement; the punch-in's monitor and take
  ml-demucs/          Stem separation (HT-Demucs on ONNX; run by separate_stems)
  ml-diarize/         Speaker diarization (pyannote's pipeline on ONNX; the diarize tool runs it)
  ml-whisper/         Transcription (ONNX Whisper; run by transcribe)
  ml-pipeline/        Shared ONNX runtime gate (finds the bundled library), model downloader (called by the user's Download click), inference cache
  memory/             Global/project markdown memory
  skills/             User skill library
  agent_profiles/     Per-session model + tool profiles
  mcp/                MCP server lifecycle
docs/                 Comprehensive technical documentation
website/              Next.js marketing site (this site)

Running tests

The full acceptance gate, as in CI:

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace -- --test-threads=1
pnpm --filter @edytlab/desktop test
pnpm --filter @edytlab/desktop test:slow-scheduler
pnpm --filter @edytlab/desktop typecheck
pnpm --filter @edytlab/desktop typecheck:e2e
pnpm --filter @edytlab/desktop test:e2e    # Playwright, Chromium
cargo test -p ai                          # single crate
cargo test -p tools test_normalize        # single test
pnpm --filter @edytlab/desktop test:watch # vitest watch mode
--test-threads=1 is required because some AI crate tests share a model-catalogue cache that is not safe for concurrent access.

Architecture overview

  1. Frontend — React 19 + Vite + Tailwind in a Tauri WebView. All state lives in Rust.
  2. Rust application layer — about 110 Tauri commands in commands.rs. Manages AppState: Store, Engine, Agent, Clipboard.
  3. Rust crates — AI subsystem, tool dispatcher, session DAG, audio engine, ML pipeline, each testable alone.

Full design: architecture.md.

Adding a new audio tool

  1. Create crates/tools/src/tool/my_tool.rs implementing the Tool trait (name, schema, invoke).
  2. Register it in ToolDispatcher::default_dispatcher() in crates/tools/src/dispatcher.rs.
  3. Write tests covering valid input, invalid input, and edge cases.
  4. Regenerate docs/tools-reference.md and document the tool in the Audio Tools Reference — tests fail until both list it.

Step by step, with code, in contributing.md §6.

Adding a new LLM provider

  1. Implement the LlmProvider trait in crates/ai/src/provider.rs.
  2. Add it to SUPPORTED_PROVIDER_IDS and the provider_from_id() factory.
  3. Give it an arm in crates/ai/src/models.rs so its model list loads.
  4. Update ProviderId in tauri-bridge.ts and the provider list in Settings.tsx. Keychain slots need no code — they are keyed by provider id.

Details in contributing.md §7.

Commit and PR process

  • Branch naming: claude/feature/<kebab-summary> or claude/fix/<kebab-summary>.
  • Commits follow Conventional Commits: feat(tools): add spectral repair tool.
  • Open PRs as drafts. Flip to ready when CI passes.
  • PRs are squash-merged. One concern per PR.
  • Run the full acceptance gate before pushing; CI blocks merge on any failure.

CI / release pipeline

ci.yml runs on every push to main and every PR: fmt → clippy → cargo test → frontend tests → frontend build, on macOS 15, Windows latest and Ubuntu 22.04, plus a Playwright job (Chromium) and the website’s tests.

On a green main push, auto-release.yml tags v<version>-dev.<run> and dispatches release-dev.yml, which builds unsigned installers for macOS, Windows and Linux. Signed releases are manual dispatches that wait on signing certificates; every release so far is unsigned.

Every installer carries ONNX Runtime 1.23.2 (and, on Windows, the Visual C++ runtime DLLs it imports), fetched by scripts/fetch-ml-runtime.sh and checked by scripts/installer-ml-runtime.py check before upload. The pin is in apps/desktop/src-tauri/ml-runtime.json. A build from source has none unless ORT_DYLIB_PATH names one, and Settings says so. The runtime carries no model.

Documentation

All documentation is in docs/: github.com/laadtushar/edytlab/tree/main/docs. Update docs in the same PR as the code.