Understanding the escrcpy Monorepo Structure: A Deep Dive into the pnpm + Turborepo Architecture
escrcpy is organized as a pnpm + Turborepo monorepo that separates the Electron UI, reusable workspace packages, and documentation into distinct directories orchestrated by turbo.json.
The escrcpy repository (viarotel-org/escrcpy) serves as a modern Android screen mirroring application built on Electron. Its monorepo structure enables independent development of the scrcpy protocol stack, device management utilities, and the main desktop interface while maintaining tight integration through shared workspace tooling.
Top-Level Directory Layout
The repository root contains three primary directories that define the architecture:
desktop/– The Electron application housing both main-process logic and renderer windows.packages/– Reusable libraries including the scrcpy protocol implementation, IPC layers, and device control modules.docs/– VitePress-powered documentation supporting multiple languages.
Additional directories like scripts/ and configs/ contain build and CI utilities, while pnpm-workspace.yaml defines the workspace boundaries.
The Desktop Application Layer
The desktop/ directory contains the complete Electron application, split between the main Node.js process and renderer windows built with Vite.
Main Process Entry Point
The application's lifecycle begins at desktop/electron/main.js. This file bootstraps the Electron environment using the plugin-based architecture provided by @escrcpy/electron-setup.
According to the source code, the main process loads plugins from @escrcpy/electron-setup and initializes the application window manager. This modular approach allows features to be registered dynamically rather than hard-coding them in the main entry file.
Renderer Windows Configuration
Unlike standard Electron apps with a single window, escrcpy manages multiple distinct renderer contexts. The desktop/vite.config.js defines separate Vite build entries for each window type:
main– Primary interfacecontrol– Device control panelexplorer– File managementcopilot– AI assistance featuresterminal– Shell accessautomation– Scripting interfacemirror– Screen mirroring view
Each entry point compiles independently while sharing common dependencies through the workspace configuration.
Workspace Packages Architecture
The packages/ directory contains six core libraries that implement the business logic independently from the Electron shell.
Core Electron Infrastructure
electron-setup/ provides the foundational plugin and window management primitives. The core API resides in packages/electron-setup/main/index.ts, exposing a window API for registering main-process modules. This abstraction layer allows the desktop application to instantiate and manage windows without directly coupling to Electron APIs.
electron-ipcx/ implements a function-friendly IPC contract between the main and renderer processes. It exposes ipcxRenderer and ipcxMain utilities used by the preload layer, replacing raw ipcMain/ipcRenderer calls with type-safe function invocations.
Scrcpy Protocol Implementation
wscrcpy/ is a self-contained Vue + TypeScript module that implements the complete scrcpy protocol stack. It exports two distinct APIs:
- Renderer-facing API –
Wscrcpycomponent and composables for the UI layer. - Main-process API – ByteBridge factory accessible via
@escrcpy/wscrcpy/main.
This separation allows the protocol logic to remain agnostic of the Electron context while providing optimized entry points for each process type.
Device Control & Utilities
madb/ implements an MCP (Model Context Protocol) server for AI-agent Android device control via ADB/Yadb interfaces.
adbx/ serves as an injected adbkit layer that prefers yadb when available on the host device, providing enhanced performance over standard ADB connections.
shared/ contains platform-neutral utilities for device handling, networking, and mathematical operations used across all packages. The export hub resides at packages/shared/src/index.ts.
Build System and Task Orchestration
The monorepo leverages Turborepo (configured in turbo.json) to orchestrate builds and development commands across packages, while pnpm resolves workspace dependencies through pnpm-workspace.yaml.
Common development workflows include:
# Install all workspace dependencies
corepack enable pnpm && pnpm install
# Start the development environment (Turbo launches the Electron Vite server on port 1535)
pnpm dev
# Run type-check only for the wscrcpy package
pnpm --filter @escrcpy/wscrcpy typecheck
# Build the whole app for the current platform
pnpm build
# Sync i18n keys after editing locale JSON files
pnpm lang-sync
The --filter flag allows targeted operations on specific workspace packages without building the entire tree, significantly improving iteration speed during development.
Key Entry Points and File References
| File | Description |
|---|---|
desktop/electron/main.js |
Main-process entry point; loads plugins from @escrcpy/electron-setup. |
desktop/vite.config.js |
Vite configuration defining multiple renderer windows. |
packages/electron-setup/main/index.ts |
Core API for registering application modules and windows. |
packages/electron-ipcx/README.md |
Documentation of the IPC contract between renderer and main processes. |
packages/wscrcpy/ |
Vue/TS scrcpy protocol implementation with dual-process API. |
packages/shared/src/index.ts |
Export hub for platform-neutral utilities. |
docs/en/guide/started.md |
User-facing getting started guide. |
Summary
- escrcpy uses a pnpm + Turborepo architecture to separate concerns between the Electron shell and business logic.
- The
desktop/directory contains the main process entry atdesktop/electron/main.jsand multi-window Vite configuration. - Six workspace packages in
packages/handle IPC, protocol implementation, and device control, withwscrcpybeing the core scrcpy stack. - Turborepo orchestrates builds through
turbo.json, whilepnpmworkspaces manage dependency linking. - Development commands like
pnpm --filter @escrcpy/wscrcpy typecheckenable targeted package operations.
Frequently Asked Questions
What build tools does escrcpy use for its monorepo structure?
escrcpy uses pnpm for package management and Turborepo for task orchestration. The pnpm-workspace.yaml file defines the workspace boundaries (including desktop/ and packages/*), while turbo.json configures the build pipeline and task dependencies. This combination enables efficient caching and parallel execution across the Electron application and workspace libraries.
How does the desktop application handle multiple renderer windows?
The application defines multiple entry points in desktop/vite.config.js, specifying separate builds for windows like main, control, explorer, copilot, terminal, automation, and mirror. Each window operates as an independent Vite entry point while sharing common dependencies through the workspace configuration, allowing specialized UI contexts without code duplication.
What is the purpose of the wscrcpy package in the monorepo?
wscrcpy is a self-contained Vue + TypeScript module that implements the complete scrcpy protocol stack for Android screen mirroring. It provides a renderer-facing API with the Wscrcpy component and composables for the UI, plus a main-process ByteBridge factory accessible via @escrcpy/wscrcpy/main. This dual-export pattern keeps the protocol logic decoupled from Electron specifics while offering optimized APIs for each process type.
How do I run commands for a specific workspace package?
Use the pnpm --filter flag followed by the package name as defined in its package.json. For example, pnpm --filter @escrcpy/wscrcpy typecheck runs the type-checking script only for the wscrcpy package. This filtering capability allows developers to lint, test, or build individual packages without waiting for the entire monorepo to process, significantly improving development velocity.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →