Tech stack
Flow is a Rust orchestration core with a single React UI delivered through several shells. This page maps the stack for anyone working on or extending the platform.
The stack at a glance
Section titled “The stack at a glance”| Layer | Technology |
|---|---|
| Orchestration core | Rust - domain types, executor, adapters, credential custody, model runtime bridge |
| Desktop shell | Tauri 2 (native WebView, OS credential-manager integration) |
| UI | React + TypeScript, built with Vite |
| Visual editor | React Flow (@xyflow/react) |
| Shared contracts | @flow/shared-types - TypeScript mirrors of the Rust domain types |
| Local inference | Managed llama.cpp llama-server subprocess |
| Storage | SQLite (execution history, schedules), JSON settings, OS keyring for secrets |
Workspace layout
Section titled “Workspace layout”apps/frontend the mono React UI (+ src-tauri desktop shell)apps/shared-types TypeScript contracts shared with any hostapps/website this marketing + docs sitecrates/* the Rust platform modulesCrate layering (depth-ordered)
Section titled “Crate layering (depth-ordered)”flow-domain pure types ├─ flow-security keyring, PII sanitizer, sandbox profiles ├─ flow-storage SQLite store ├─ flow-execution executor, EventSink trait, adapter registry ├─ flow-adapter-ai AI provider registry (local + cloud HTTP) ├─ flow-adapter-* shell / fs / cli / utility action dispatch ├─ flow-application FlowApp - the orchestrator owning all of the above └─ shells Tauri desktop, flow-server (HTTP/SSE), flow-cliTwo crates sit outside the chain. flow-dsl is an independent, pure
parser/serializer with no I/O. flow-spec is build-time only, and it feeds
the spec pipeline below. flow-models-server owns the managed llama-server
lifecycle and is reused by every edition.
The thin-host rule
Section titled “The thin-host rule”The Tauri shell does three things. It registers command wrappers, manages a single
FlowApp instance, and forwards events. All real logic lives in the shared
core, which is exercised by integration tests without any Tauri dependency.
This separation matters because it lets the same core run headless in the CLI and
behind the server’s HTTP API. Keep new business logic out of the shell.
One UI, one backend
Section titled “One UI, one backend”Every edition renders the same React app and drives the same core. A host
facade in the frontend routes each call to the active transport, which is
selected at runtime. The transport is either Tauri IPC for the desktop with an
in-process core, or HTTP/SSE for the browser with flow-server. All IPC call
sites are consolidated in one services directory by convention, and components
never invoke the backend directly.
Four event streams cross the frontend/core boundary:
| Event | Payload |
|---|---|
flow:execution | The tagged execution-event union (node lifecycle, logs, summaries) |
models:install_progress | { stage, current, total, message } download/engine progress |
models:registered | A model id, from the boot scan |
models:scan_complete | Boot scan finished |
The DSL spec pipeline
Section titled “The DSL spec pipeline”The DSL reference is generated, not hand-edited. A build script runs the spec crate’s descriptor dump and concatenates the hand-authored grammar and examples with the generated node and adapter references into one compiled spec file. That file feeds two consumers: the application core embeds it as the flow-generator system prompt, and the sibling model-training repository syncs it as training data. Sync direction is one-way, from this repository outward.
Two invariants protect this pipeline:
- The DSL has exactly five node types with scalar-only bodies.
serialize(parse(s))is a canonical-form fixed point, and it is preserved in every DSL change.
Related
Section titled “Related”- Development guidelines
- API documentation
- Adapters - the extension surface.