|
|
|
The gRPC Protocol Layer for the Land Editor 🏞️
Every component in Land talks to every other component through a well-defined, strongly-typed schema. That schema is Vine.
"One .proto file. Every service. Type safety from compile time to wire."
Vine is the communication layer for the Land Code Editor. It defines how every component talks to every other component - what messages they can send, what responses they expect, and how data streams between them.
All IPC in Land is defined in a single file: Proto/Vine.proto. This file
declares every RPC method, every message type, and every streaming channel the
system needs. From this one source, the build system generates type-safe Rust
clients and servers (using tonic / prost), while the Node.js extension
host mirrors the same definitions in TypeScript.
The components that speak Vine: Mountain ⛰️ (the Rust
backend), Cocoon 🦋 (the Node.js extension host),
Air 🪁 (the background daemon), and
Grove 🌳 (the Rust/WASM extension host).
Vine is engineered to:
- Centralize Protocol Contracts - One
.protofile is the sole authority for everygRPCservice, message, and streaming envelope in the Land ecosystem. - Generate Type-Safe Bindings -
Prost-backed Rust code is generated at build time fromProto/Vine.proto, giving every consumer compile-time guarantees against wire-format drift. - Provide Runtime Scaffolding - Client connection pools, server bind helpers, notification handler dispatch trees, and a bidirectional envelope multiplexer ship as cargo features.
- Support Multiple Embedders - The
VineHosttrait abstracts the embedder runtime (Mountain,Air,Cocoon-Rust) so a single handler tree works against any host.
Single-Source Protocol - Every gRPC contract lives in Proto/Vine.proto,
the canonical specification for MountainService (hosted by Mountain) and
CocoonService (hosted by the Cocoon sidecar). build.rs feeds this file to
tonic-prost-build, producing Source/Generated/vine.rs with all message
types, clients, and server traits.
Feature-Gated Runtime - The crate is split into three optional features so
consumers only compile what they need: client (connection pool, request
dispatch, health checks), server (bind helpers, notification handler tree),
and multiplexer (bidirectional streaming over a single HTTP/2 connection).
Embedder-Agnostic Handler Tree - The VineHost trait is the seam between
Vine and its consumer runtime. Notification handlers operate on &dyn VineHost,
so the same handler tree works in Mountain (Tauri renderer dispatch), Air
(daemon-only, no renderer), or any future embedder. Every handler file lives
under Source/Server/Notification/.
Client Connection Pool - A DashMap-backed pool of tonic gRPC channels
with exponential-backoff connection logic, subscriber fan-out for notification
broadcast, and atomic shutdown signalling. Entries under Source/Client/ cover
every client-side operation.
Structured Error Types - VineError enumerates every failure mode with
recoverability predicates and tonic::Status mapping. Callers use
IsRecoverable() to decide between retry, fallback, and surfacing.
Bidirectional Multiplexer - Source/Multiplexer.rs implements the streaming
envelope protocol (OpenChannelFromCocoon / OpenChannelFromMountain, per
LAND-PATCH B7-S6 P14.1) for concurrent dispatch over a single HTTP/2 stream.
| Principle | Description | Key Components |
|---|---|---|
| Single Authority | One .proto file defines every contract. No duplication, no drift. |
Proto/Vine.proto, Source/Generated/, build.rs |
| Type Safety | Prost-generated code ensures every message, RPC, and streaming frame matches the proto schema at compile time. |
Source/Generated/vine.rs, tonic-prost-build |
| Transport Agnosticism | The VineHost trait and tonic's transport layer abstract the actual network substrate. Local [::1] or remote - same handler tree. |
VineHost trait, tonic Server/Channel |
| Composability | Each feature module (client, server, multiplexer) compiles independently so consumers pay only for what they use. |
Cargo.toml features, Source/Client/, Source/Server/, Source/Multiplexer.rs |
graph LR
classDef vine fill:#e8ffe8,stroke:#27ae60,stroke-width:2px,color:#0a3a0a;
classDef mountain fill:#f0d0ff,stroke:#9b59b6,stroke-width:2px,color:#2c0050;
classDef cocoon fill:#d0d8ff,stroke:#4a6fa5,stroke-width:2px,color:#001050;
classDef grove fill:#d4f5d4,stroke:#27ae60,stroke-width:1px,color:#0a3a0a;
classDef proto fill:#fff3c0,stroke:#f39c12,stroke-width:1px,stroke-dasharray:5 5,color:#5a3e00;
subgraph PROTO["Vine.proto - Contract Definition 🌿"]
direction TB
MountainSvc["MountainService ProcessCocoonRequest · SendCocoonNotification CancelOperation · OpenChannelFromCocoon (streaming)"]:::proto
CocoonSvc["CocoonService ProcessMountainRequest · SendMountainNotification CancelOperation · OpenChannelFromMountain (streaming)"]:::proto
end
subgraph VINE["Vine 🌿 - Crate"]
direction TB
Generated["Generated/ prost message types + tonic stubs"]:::vine
Client["Client/ connection pool · dispatch · health checks"]:::vine
Server["Server/ bind helpers · notification handler tree"]:::vine
Multiplexer["Multiplexer/ bidirectional streaming envelope"]:::vine
HostTrait["Host/ (VineHost trait) embedder seam"]:::vine
Generated --- Client
Generated --- Server
Client --- Multiplexer
Server --- Multiplexer
Server --- HostTrait
end
subgraph MOUNTAIN["Mountain ⛰️"]
VineServer["Vine gRPC Server (tonic) hosts MountainService"]:::mountain
end
subgraph COCOON["Cocoon 🦋"]
GRPCClient["Services/Mountain/gRPC/Client.ts"]:::cocoon
GRPCServer["Services/gRPC/Server/ - CocoonService impl"]:::cocoon
end
subgraph GROVE_S["Grove 🌳"]
GroveClient["gRPCTransport.rs speaks Vine as client"]:::grove
end
MountainSvc -.defines.-> VineServer
CocoonSvc -.defines.-> GRPCServer
VineServer <-- bidirectional gRPC :50052 --> GRPCClient
VineServer --> GRPCServer
VineServer <-- gRPC :50052 --> GroveClient
VineServer -- cargo dep --> VINE
Connection paths:
| Path | Protocol | Use Case |
|---|---|---|
| Mountain ⛰️ → Cocoon 🦋 | gRPC on port 50052 |
Backend-to-extension-host dispatch |
| Cocoon 🦋 → Mountain ⛰️ | gRPC on port 50051 |
Extension invocation of editor operations |
| Air 🪁 → Mountain ⛰️ | gRPC on port 50051 |
Daemon queries for indexing/update/download tasks |
| Mountain ⛰️ → Air 🪁 | gRPC on port 50053 |
Editor-to-daemon service calls |
| Grove 🌳 → Mountain ⛰️ | gRPC on port 50052 |
Native WASM extension host communication |
| Multiplexer stream | HTTP/2 bidirectional streaming | Concurrent dispatch over single connection |
| Component | Path | Description |
|---|---|---|
| Proto Definition | Proto/Vine.proto |
Canonical gRPC service and message definitions for the entire Land ecosystem |
| Generated Bindings | Source/Generated/vine.rs |
tonic-prost-build output: message types, client stubs, server traits |
| Client Connection Pool | Source/Client/ |
DashMap-backed pool of tonic channels with exponential-backoff connect, notification fan-out, and health checks |
| SendRequest | Source/Client/SendRequest.rs |
Unary request dispatch with configurable timeout and streaming-multiplexer fast path |
| SendNotification | Source/Client/SendNotification.rs |
Fire-and-forget notification dispatch with broadcast fan-out |
| Server Bind Helpers | Source/Server/ |
SpawnBindTask, SpawnBindTaskWithShutdown, ValidateSocketAddress - boilerplate every embedder needs |
| Notification Handlers | Source/Server/Notification/ |
Per-file handler tree for Cocoon → Mountain notifications with payload reshaping, coalescing, and multi-step logic |
| VineHost Trait | Source/Host.rs |
Embedder seam: application state access, renderer emission, IPC provider, command/SCM/terminal/language registration |
| Error Types | Source/Error.rs |
VineError enum with recoverability predicates and tonic::Status mapping |
| Multiplexer | Source/Multiplexer.rs |
Bidirectional streaming envelope protocol (LAND-PATCH B7-S6 P14.1) |
| Library Root | Source/Library.rs |
Crate root: module declarations, protocol constants (ProtocolVersion, DefaultMaxMessageSize, default addresses) |
Element/Vine/
├── Proto/
│ └── Vine.proto # Canonical gRPC contract (MountainService + CocoonService)
├── Source/
│ ├── Library.rs # Library root (rlib)
│ ├── DevLog.rs # Development logging infrastructure
│ ├── Error.rs # VineError enum + From impls + tonic::Status mapping
│ ├── Host.rs # VineHost trait + IPCProvider + ApplicationStateAccess + RendererEmitter
│ ├── Generated/
│ │ ├── mod.rs # Module docs + re-exports
│ │ └── vine.rs # prost-built message types + tonic clients/servers
│ ├── Client/ # Client-side gRPC wrappers (feature = "client")
│ │ ├── mod.rs # Module docs + public module list
│ │ ├── Shared.rs # Module-private state (statics, helpers, constants)
│ │ ├── MarkShutdown.rs # Process-wide shutdown flag
│ │ ├── IsShuttingDown.rs # Shutdown flag reader
│ │ ├── NotificationFrame.rs # Broadcast payload struct
│ │ ├── SubscribeNotifications.rs # Notification fan-out registration
│ │ ├── SubscriberCount.rs # Active subscriber counter
│ │ ├── ConnectToSideCar.rs # Pool-lifecycle connect (3-attempt backoff)
│ │ ├── DisconnectFromSideCar.rs # Pool-lifecycle disconnect
│ │ ├── TryConnectSingle.rs # Single connection attempt with h2 tuning
│ │ ├── IsClientConnected.rs # Pool readiness check
│ │ ├── WaitForClientConnection.rs # Boot-race-friendly async readiness
│ │ ├── CheckSideCarHealth.rs # Pool + metadata health summary
│ │ ├── SendRequest.rs # Unary request dispatch with timeout + streaming fast path
│ │ ├── SendNotification.rs # Fire-and-forget notification dispatch
│ │ ├── PublishNotification.rs # Private broadcast publisher
│ │ └── PublishNotificationFromMux.rs # Pub(crate) multiplexer broadcast publisher
│ ├── Server/ # Server-side gRPC scaffolding (feature = "server")
│ │ ├── mod.rs # Module docs + embedder call pattern
│ │ ├── Constants.rs # Default ports / timeouts / message-size cap
│ │ ├── ValidateSocketAddress.rs # Port-and-format pre-flight check
│ │ ├── SpawnBindTask.rs # Detached tokio::spawn server runner
│ │ ├── SpawnBindTaskWithShutdown.rs # Drain-capable server runner
│ │ └── Notification/ # Cocoon → Mountain handler tree
│ │ ├── mod.rs # Handler module listing with logic annotations
│ │ ├── Support/
│ │ │ ├── mod.rs # Shared handler utilities
│ │ │ ├── RelayToSky.rs # Single sky-event forward
│ │ │ └── UnregisterByHandle.rs # Provider unregistration by handle
│ │ ├── OutputAppendLine.rs # Output channel append with payload reshape
│ │ ├── OutputChannelAppend.rs
│ │ ├── OutputChannelCoalesce.rs # Channel-drain coalescer
│ │ ├── OutputChannelHide.rs
│ │ ├── OutputChannelReplace.rs
│ │ ├── OutputReplace.rs
│ │ ├── ProgressStart.rs # Progress lifecycle handlers with coalescing
│ │ ├── ProgressReport.rs
│ │ ├── ProgressEnd.rs
│ │ ├── WebviewDispose.rs # Webview lifecycle management
│ │ ├── WebviewPostMessage.rs
│ │ ├── WebviewLifecycle.rs
│ │ ├── WebviewReady.rs
│ │ ├── WindowShowMessage.rs # Window message display
│ │ ├── DecorationTypeLifecycle.rs # Text-editor decoration batching
│ │ ├── SetTextEditorDecorations.rs
│ │ ├── ApplyTextEdits.rs # Editor text mutations
│ │ ├── SetLanguageConfiguration.rs # Language-feature configuration
│ │ ├── RegisterCommand.rs # Command registry operations
│ │ ├── UnregisterCommand.rs
│ │ ├── RegisterLanguageProvider.rs # Language-feature provider registration
│ │ ├── StatusBarLifecycle.rs # StatusBar item lifecycle
│ │ ├── StatusBarMessage.rs
│ │ ├── SetStatusBarText.rs
│ │ ├── DisposeStatusBarItem.rs
│ │ ├── DebugLifecycle.rs # Debug adapter lifecycle
│ │ ├── TerminalLifecycle.rs # Terminal lifecycle management
│ │ ├── WindowCreateTerminal.rs
│ │ ├── RegisterScmProvider.rs # SCM provider registration
│ │ ├── RegisterScmResourceGroup.rs
│ │ ├── UnregisterScmProvider.rs
│ │ ├── UpdateScmGroup.rs # SCM group update dispatch
│ │ ├── OpenExternal.rs # External URI/URL opening
│ │ ├── SecurityIncident.rs # Security incident notification
│ │ └── ... # Pure-relay atoms inlined in Mountain dispatcher
│ └── Multiplexer.rs # Bidirectional streaming envelope (feature = "multiplexer")
├── build.rs # tonic-build + tonic-prost-build codegen
├── Cargo.toml # Crate manifest with feature flags
└── Documentation/
└── GitHub/
├── Architecture.md # Full protocol specification and module structure
└── DeepDive.md # In-depth technical details
Vine is the gRPC contract layer that wires every Land component together. It
is not the implementation - it is the specification and the shared runtime that
all implementations conform to:
| Component | Role | Port | Consumes Vine |
|---|---|---|---|
| Mountain ⛰️ | Desktop shell, hosts MountainService |
50051 | server feature |
| Cocoon 🦋 | Node.js extension host, hosts CocoonService |
50052 | TypeScript mirror of proto |
| Air 🪁 | Background daemon, hosts AirService |
50053 | client feature |
| Grove 🌳 | Rust/WASM extension host |
- | client feature via gRPCTransport |
Vine is part of the Land networking/IPC connectivity stack alongside
Air 🪁 (background daemon, uses Vine/gRPC on port 50053 for
AirService) and Mist 🌫️ (DNS isolation, used by Air's HTTP
client).
The VineHost trait abstracts the embedder runtime so a single notification
handler tree works across all consumers. Mountain wires EmitToRenderer to
tauri::WebviewWindow::emit; Air leaves it as a no-op. The client feature
gives every consumer a connection pool, health checks, and exponential-backoff
reconnect - all driven by the same Proto/Vine.proto contract.
- Rust 1.95.0 or later (workspace MSRV; edition 2024)
- Protocol Buffer compiler (
protoc, optional - only needed for proto file modifications)
cd Element/Vine
cargo build --release# All features enabled
cargo build --release --all-features
# Server only (for embedders hosting a Vine service)
cargo build --release --features server
# Client only (for embedders calling Vine services)
cargo build --release --features client
# With bidirectional multiplexer
cargo build --release --features server,client,multiplexer| Feature | Default | Description |
|---|---|---|
default |
- | Enables server and client |
server |
✅ | Server-side gRPC handler scaffolding (Mountain consumes this) |
client |
✅ | Client-side gRPC stubs and connection pool (Air, Grove consume this) |
multiplexer |
Bidirectional envelope multiplexer (LAND-PATCH B7-S6 P14.1) |
use Vine::{
Client::{ConnectToSideCar, SendRequest, SendNotification},
Server::{Constants, SpawnBindTask, ValidateSocketAddress},
Error::VineError,
};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Server-side: bind a Vine service
let Address = ValidateSocketAddress::Fn("[::1]:50051", "MountainService")?;
let Service = MyMountainServiceImpl::new(state);
let Wrapped = MountainServiceServer::new(Service)
.max_decoding_message_size(Constants::MAX_MESSAGE_SIZE);
let Router = tonic::transport::Server::builder().add_service(Wrapped);
SpawnBindTask::Fn("MountainService".to_string(), Address, Router);
// Client-side: connect and dispatch
ConnectToSideCar::Fn("cocoon-main", "[::1]:50052").await?;
SendRequest::Fn("cocoon-main", "some-method", payload, None).await?;
Ok(())
}Vine itself does not enforce security - it is a protocol layer. Security boundaries live in the embedders:
| Layer | Mechanism |
|---|---|
| Transport | tonic enforces HTTP/2 TLS when configured with certificates; Vine transports bind to [::1] (localhost) by default |
| Message validation | ValidateSocketAddress pre-flight checks; DefaultMaxMessageSize (4 MB) enforced at the envelope boundary |
| Type safety | Prost-generated code ensures every message conforms to the proto schema at compile time |
| Feature isolation | Each cargo feature (client, server, multiplexer) compiles independently - embedders only compile what they use |
For extension sandboxing, see Grove 🌳 (hardware-enforced
WASMtime isolation). For renderer isolation, see
Mountain ⛰️ (process-per-window via Tauri).
Vine is designed to be compatible with:
| Target | Integration |
|---|---|
| Mountain ⛰️ | Hosts MountainService; implements VineHost with Tauri renderer dispatch |
| Cocoon 🦋 | TypeScript @grpc/grpc-js clients mirror MountainService and CocoonService proto definitions |
| Air 🪁 | Consumes client feature for daemon-side gRPC calls to Mountain |
| Grove 🌳 | Consumes client feature via gRPCTransport for native WASM extension host communication |
| tonic | Built on tonic 0.x / prost - any tonic-compatible gRPC client can speak Vine |
| 🟠 Low-Level Shim | 🔵 Coverage Shim |
|---|---|
Tier: TierShim=Own|Preempt |
Tier: TierShim=Proxy|Replace |
| Engine prototype hooks | Service routing + audit |
| Error, Emitter, Cancel, Dispose, Async, Timing | IPC SwallowMap, DI proxy, AuditLog |
This Element supports the Land deep-shim interception system. The shim intercepts VS Code engine events at both the JavaScript prototype level (🟠 orange) and the application service level (🔵 blue). Gated behind
TierShimenv var (default:None- zero overhead). See the Shim documentation.
- Architecture Overview - Internal module structure and protocol specification
- Deep Dive - In-depth technical details
- Land Documentation - Complete documentation index
- Air 🪁 - Background daemon using Vine/
gRPCon port 50053 - GitHub - Mist 🌫️ - DNS isolation for the private network - GitHub
- Mountain ⛰️ -
gRPCserver host - GitHub - Cocoon 🦋 -
gRPCclient host - GitHub - Grove 🌳 - Native
Rust/WASMextension host - GitHub
This project is released into the public domain under the Creative Commons CC0
Universal license. You are free to use, modify, distribute, and build upon
this work for any purpose, without any restrictions. For the full legal text,
see the LICENSE
file.
Stay updated with our progress! See
CHANGELOG.md
for a history of changes.
Land 🏞️ is proud to be an open-source endeavor. Our journey is significantly supported by the organizations and projects that believe in the future of open-source software.
This project is funded through NGI0 Commons Fund, a fund established by NLnet with financial support from the European Commission's Next Generation Internet program. Learn more at the NLnet project page.
| Land | PlayForm | NLnet | NGI0 Commons Fund |
|---|---|---|---|
Project Maintainers: Source Open (Source/Open@editor.land) | GitHub Repository | Report an Issue | Security Policy