Workflows
Application Startup and Handshake
How Mountain, Cocoon, and the Wind workbench initialise and establish their IPC connections on every launch.
Land starts in three overlapping phases: the native Mountain binary starts its gRPC listener and spawns the Cocoon Node.js sidecar, Cocoon bootstraps and completes the initExtensionHost handshake, and the Wind workbench renders in the Tauri webview. The Mountain↔Cocoon handshake is the hard ordering constraint that gates extension activation; everything else proceeds in parallel.
This is the foundational workflow that enables all others. Once the handshake completes and the workbench paints its first frame, the system is ready for user interaction and all dependent workflows — opening files, executing commands, language features — can proceed.
sequenceDiagram
participant User as User
participant Mountain as Mountain (Native Backend)
participant Cocoon as Cocoon (Extension Host)
participant VSCode as VSCode (Workbench UI)
User->>Mountain: Launch Application
activate Mountain
Mountain->>Mountain: Create AppState & AppRuntime
Mountain->>Mountain: Load Configuration
Mountain->>Mountain: Scan Extensions
Mountain->>Mountain: Start gRPC Server
Mountain->>Cocoon: Spawn Node.js Process (bootstrap-fork.js)
deactivate Mountain
activate Cocoon
Cocoon->>Mountain: $initialHandshake gRPC notification
deactivate Cocoon
activate Mountain
Mountain->>Mountain: Gather InitData from AppState
Mountain->>Cocoon: initExtensionHost gRPC request
deactivate Mountain
activate Cocoon
Cocoon->>Cocoon: Create InitDataLayer
Cocoon->>Cocoon: Run FullAppInitialization
Cocoon->>Cocoon: Install RequireInterceptor
Cocoon->>Cocoon: Activate Startup Extensions
deactivate Cocoon
User->>VSCode: Open Window (index.html)
activate VSCode
VSCode->>VSCode: Preload.ts shims window.vscode
VSCode->>VSCode: Create AppLayer Services
VSCode->>VSCode: Instantiate Workbench
VSCode->>VSCode: Render UI Parts (Activity Bar, Sidebar, etc.)
deactivate VSCode
Note over Mountain,Cocoon: System Ready for User InteractionPhase 1 — Mountain native startup
The OS launches the Mountain binary. The
mainfunction inBinary/Main/Entry.rscreates Tauri’sBuilderand configures the.setup()hook. Inside the hook, the centralAppStateis created and managed by Tauri, theMountainEnvironment(which implements everyCommontrait) is created, theAppRuntime(the engine for running effects) is created wrapping the environment, and a Tokio background task is spawned for post-setup work.Inside the background task, four steps run in strict order:
InitializeConfiguration— reads allsettings.jsonfiles from disk intoAppState.Configuration.ExtensionManagement— walks extension roots and loads manifests intoAppState.Extensions. If a pre-bakedextensions.manifest.jsonexists on disk (written byMaintain/Build/Manifest/PreBake.tsduring the build’sbeforeBundleCommand), this step completes in under 50 ms. On first boot or when the cache is absent, a paralleljoin_alllive scan runs (~1200 ms) and caches the result for subsequent launches.vine::server::Initialize— starts the Vine gRPC server (default port 50051) and begins listening for connections from Cocoon.InitializeCocoon(ProcessManagement/CocoonManagement.rs) — spawns the Node.js sidecar process. It constructs a detailed environment that includesVSCODE_PARENT_PID, so the child terminates automatically when Mountain exits. The exact command is:node ./Element/Cocoon/Scripts/cocoon/bootstrap-fork.jsMountain then waits up to 30 seconds for Cocoon’s
$initialHandshakegRPC notification.
Phase 2 — Cocoon bootstrap and handshake
Cocoon’s Bootstrap.ts runs seven stages in strict order:
Environment — records Node.js version, platform, and architecture.
Configuration — resolves
MOUNTAIN_GRPC_PORT(50051) andCOCOON_GRPC_PORT(50052); populatesglobalThis.__cocoonBootstrapConfigandglobalThis.__LandTiers.RPCServer — binds Cocoon’s own gRPC server on port 50052. This must complete before Mountain’s 30-second connection budget expires.
ModuleInterceptor — installs the
require()interceptor, remappingelectronto Tauri stubs and patching VS Code bundle loading.MountainConnection — TCP-probes Mountain on port 50051, opens the gRPC channel, and sends the
$initialHandshakenotification to signal readiness.Extensions — activates enabled extensions concurrently (up to 8 in parallel). Extension activation uses topological ordering: if extension A declares
extensionDependencies: ["B"], extension B activates first. AnInProgressset prevents circular dependency deadlocks.HealthCheck — optional final service health sweep.
Between stages 5 and 6, Mountain responds to the handshake:
Mountain receives
$initialHandshakeand callsProcessManagement/InitializationData.rs, which assembles the fullISandboxConfiguration+IExtensionHostInitDatapayload. This payload includes: workspace roots, extension list and metadata, configuration state (argv.json,settings.json,keybindings.json), registered profiles,dataFolderName(a primary crash source when missing),perfMarks,loggers,colorScheme,mainPid, and OS metadata (platform, arch, release, hostname).Mountain sends the
initExtensionHostgRPC request back to Cocoon, containing this initialization payload.Cocoon’s handler fires: it uses the payload to create and provide the
InitDataLayer, runsFullAppInitialization, resolves theExtensionHostProvider, installs theRequireInterceptorso everyrequire('vscode')returns the Cocoon shim, and activates startup extensions (*activation event). The topological ordering from the Extensions stage (step 6) ensures that extension dependency chains resolve correctly before providers register. At this point, workflows like Language Features and Webviews can begin, as extensions register their providers.
Phase 3 — Wind workbench launch
These steps run in parallel with Phase 2, starting from the moment Tauri opens the main window.
Tauri loads
index.htmlin the webview, built bySky/Source/pages/Mountain.astro. The Astro page produces the static HTML shell that bootstraps the Wind application script.Wind/Source/Preload.tsexecutes first, shimmingwindow.vscodewith Tauri-backed implementations foripcRendererandprocess. This shim is the critical bridge that allows the VS Code workbench code to run in a non-Electron, Tauri-based webview context.The main Wind entry script waits for DOM ready, then composes the
AppLayer— an Effect-TSLayerproviding every Wind service:LiveClipboardService,LiveDialogService,LiveEditorService, and all the rest. Each service is backed by Tauri IPC calls or native Rust commands, replacing the Electron APIs that VS Code’s workbench would normally consume.The layer is converted to a Runtime and the VS Code
Workbenchis instantiated vianew Workbench(...). TheWorkbenchconstructor receives the resolved service runtime as its dependency container.Workbench.startup()is then called, which kicks off the entire UI rendering lifecycle — creating every UI part: Activity Bar, Status Bar, Side Bar, Editor Part, and instantiating the editor pane itself. Each part begins requesting data from Wind services, which in turn invoke Mountain IPC for filesystem reads, command lists, configuration values, and extension contributions.As these parts are created, they trigger downstream workflows. For example, the File Explorer uses
IFileServiceto list directory contents (triggering the Opening a File workflow), and the Command Palette usesICommandService(triggering the Executing a Command workflow). Extension contributions to the UI (views, menus, keybindings) are registered via theIExtensionService, which is populated during Cocoon’s startup extension activation in Phase 2.Extension activation timing after handshake: Once Cocoon’s
initExtensionHosthandler completes (Phase 2), activated extensions begin contributing to the workbench in real-time. TheIExtensionServiceon the Wind side subscribes to a gRPC stream from Cocoon that relaysactivatedExtensionevents as each extension finishes itsactivate()call. This means the Command Palette and language features become available progressively — the first extension’s contributions appear before the last one has finished activating. The workbench does not block paint on extension activation; it renders its chrome immediately and populates contributed UI elements as the extension stream arrives.
Important
The workbench’s first meaningful paint depends on Mountain returning the InitializationData payload promptly. Delays in the extension scan (Phase 1, step 2) or the handshake round-trip (Phase 2, stage 5) directly delay first sidebar render. The pre-baked manifest and the RPCServer-before-MountainConnection bootstrap ordering are the two changes that keep first paint under 800 ms.