# aeroxy/drift architecture

> Architecture diagram of the GitHub repository aeroxy/drift, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-20). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/aeroxy/drift
- Repository: https://github.com/aeroxy/drift

## Overview

- **Overall shape:** drift is a **single Rust binary** that bundles a **React/TypeScript frontend** and a **WebSocket-based transfer engine**. The binary can act as a local server, an outbound client to another drift instance, or a one-shot CLI tool for send/list/pull operations.

- **Primary runtime boundary:** there are two peers in every transfer. One side listens on a port and serves the web UI; the other side may connect outbound to `--target`. Once connected, both peers can expose their own filesystem and browse the remote one, so the app is naturally **bidirectional** rather than “server vs client” in a fixed sense.

- **CLI entry layer:** `src/main.rs` and `src/config.rs` parse the command set (`serve`, `send`, `ls`, `pull`, plus legacy flat args) and decide whether the process should launch the web server, open an outbound session, or do a one-off transfer and exit.

- **Server subsystem:** `src/server/` contains the HTTP/WebSocket-facing backend. `ws_handler.rs` manages the encrypted WebSocket session, `file_api.rs` serves browse/info requests, `browser_transfer.rs` coordinates transfers initiated from the UI, and `transfer_receiver.rs` writes incoming data and handles extraction. This is the main boundary between the UI and filesystem.

- **Client subsystem:** `src/client/` is the outbound side that connects to a remote drift instance when `--target` is set. `browse.rs` supports remote directory listing for `ls`, `pull.rs` implements downloading from a remote host, `send.rs` handles push/send mode, and `reconnect.rs` provides session re-establishment after disconnects.

- **Protocol layer:** `src/protocol/` defines the wire contract. Control traffic uses encrypted JSON `ControlMessage` values; file payloads use a binary chunk format with a UUID and offset. The protocol is designed for concurrent requests and out-of-order replies, so correlation IDs matter to the architecture.

- **Security layer:** `src/crypto/` implements the session security model. Peers perform an **X25519 handshake**, derive directional symmetric keys with **HKDF-SHA256**, optionally authenticate with a password-based HMAC challenge/response, and then encrypt all traffic with **ChaCha20-Poly1305**. The security boundary is the network link; the code assumes trusted peers after connection.

- **Filesystem operations:** `src/fileops/` isolates local file access. `browse.rs` canonicalizes and validates browse paths against the root to prevent traversal, `reader.rs` and `writer.rs` implement chunked async I/O, and `compress.rs` / `decompress.rs` convert directories to and from `.tar.gz` for recursive folder transfer.

- **Transfer behavior:** file data moves in **64 KB chunks** over encrypted WebSocket binary frames. Files are streamed directly; folders are compressed before upload and extracted on receipt. Large transfers therefore flow through the protocol layer into chunked file I/O rather than through a single buffered payload.

- **Frontend subsystem:** `frontend/` is a React + TypeScript UI built with Vite/Bun. The main UI is a two-pane file browser with connection modal, path bar, file list, toolbar, and transfer progress bar. Hooks such as `useWebSocket` and `useTransfer` bind the UI to backend events and transfer state.

- **Embedding and packaging:** `build.rs` builds the frontend before Rust compilation, and `src/frontend.rs` serves the generated assets from the binary via embedded static files. That makes the shipped artifact self-contained: no separate web app deployment is required.

- **Operational modes:** the same codebase supports three distinct flows: interactive browsing via the web UI, direct CLI file movement (`send`, `pull`, `ls`), and reconnectable long-lived sessions. This is important for diagramming because the UI and CLI are thin entry points into the same underlying transport and filesystem subsystems.

- **Testing and validation:** frontend integration tests in `frontend/test/` spin up real drift processes, transfer actual files over WebSocket, and verify checksums plus cleanup of temporary `.drift/` directories. The tests exercise the full stack, not just isolated units.

- **Useful diagram boundary:** a good architecture diagram should show four main boxes: **CLI/runtime orchestration**, **encrypted WebSocket protocol + crypto**, **filesystem/transfer services**, and **embedded frontend UI** — with the WebSocket link as the central data path and the local filesystem as the protected backend resource.

Main entry points: [`src/server/mod.rs`](https://github.com/aeroxy/drift/blob/master/src/server/mod.rs) (Server), [`src/server/ws_handler.rs`](https://github.com/aeroxy/drift/blob/master/src/server/ws_handler.rs) (WS Handler), [`src/main.rs`](https://github.com/aeroxy/drift/blob/master/src/main.rs) (Main), [`src/client/mod.rs`](https://github.com/aeroxy/drift/blob/master/src/client/mod.rs) (Client)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_grp_runtime["Runtime"]
  node_n_main["Main<br/>rust binary<br/>[main.rs]"]
  node_n_config["Config<br/>[config.rs]"]
  node_n_server_mod["Server<br/>backend<br/>[mod.rs]"]
  node_n_client_mod["Client<br/>outbound side<br/>[mod.rs]"]
  node_n_reconnect["Reconnect<br/>session recovery<br/>[reconnect.rs]"]
end

subgraph group_grp_network["Network"]
  node_n_handshake["Handshake<br/>x25519+kdf<br/>[handshake.rs]"]
  node_n_stream["Stream Crypto<br/>cipher framing<br/>[stream.rs]"]
  node_n_codec["Codec<br/>wire encoding<br/>[codec.rs]"]
  node_n_messages["Messages<br/>control schema<br/>[messages.rs]"]
  node_n_transfer_proto["Transfer Proto<br/>chunk format<br/>[transfer.rs]"]
  node_n_ws_handler["WS Handler<br/>session endpoint<br/>[ws_handler.rs]"]
end

subgraph group_grp_storage["Transfer Services"]
  node_n_file_api["File API<br/>browse api<br/>[file_api.rs]"]
  node_n_browser_transfer["Browser Transfer<br/>ui transfer coordinator"]
  node_n_transfer_receiver["Receiver<br/>ingest sink"]
  node_n_browse_fs["Browse FS<br/>path guard<br/>[browse.rs]"]
  node_n_reader_writer["Chunk I/O<br/>streamed io<br/>[reader.rs]"]
  node_n_compress["Compress<br/>tar.gz packer<br/>[compress.rs]"]
  node_n_decompress["Decompress<br/>tar.gz unpacker<br/>[decompress.rs]"]
end

subgraph group_grp_frontend["Frontend"]
  node_n_frontend_rs["Frontend Embed<br/>asset host<br/>[frontend.rs]"]
  node_n_app["App UI<br/>react ui<br/>[App.tsx]"]
  node_n_ws_hook["WS Hook<br/>frontend hook<br/>[useWebSocket.ts]"]
  node_n_transfer_hook["Transfer Hook<br/>frontend hook<br/>[useTransfer.ts]"]
end

node_n_main -->|"parses"| node_n_config
node_n_main -->|"starts"| node_n_server_mod
node_n_main -->|"opens"| node_n_client_mod
node_n_client_mod -->|"reconnects"| node_n_reconnect
node_n_server_mod -->|"accepts"| node_n_ws_handler
node_n_ws_handler -->|"negotiates"| node_n_handshake
node_n_ws_handler -->|"encrypts"| node_n_stream
node_n_stream -->|"frames"| node_n_codec
node_n_codec -->|"encodes"| node_n_messages
node_n_codec -->|"encodes"| node_n_transfer_proto
node_n_server_mod -->|"routes"| node_n_file_api
node_n_server_mod -->|"coordinates"| node_n_browser_transfer
node_n_browser_transfer -->|"delivers"| node_n_transfer_receiver
node_n_file_api -->|"validates"| node_n_browse_fs
node_n_transfer_receiver -->|"streams"| node_n_reader_writer
node_n_browser_transfer -->|"packages"| node_n_compress
node_n_transfer_receiver -->|"extracts"| node_n_decompress
node_n_reader_writer -->|"moves"| node_n_transfer_proto
node_n_frontend_rs -->|"serves"| node_n_app
node_n_app -->|"binds"| node_n_ws_hook
node_n_app -->|"binds"| node_n_transfer_hook
node_n_client_mod -->|"connects"| node_n_ws_handler

click node_n_main "https://github.com/aeroxy/drift/blob/master/src/main.rs"
click node_n_config "https://github.com/aeroxy/drift/blob/master/src/config.rs"
click node_n_server_mod "https://github.com/aeroxy/drift/blob/master/src/server/mod.rs"
click node_n_client_mod "https://github.com/aeroxy/drift/blob/master/src/client/mod.rs"
click node_n_reconnect "https://github.com/aeroxy/drift/blob/master/src/client/reconnect.rs"
click node_n_handshake "https://github.com/aeroxy/drift/blob/master/src/crypto/handshake.rs"
click node_n_stream "https://github.com/aeroxy/drift/blob/master/src/crypto/stream.rs"
click node_n_codec "https://github.com/aeroxy/drift/blob/master/src/protocol/codec.rs"
click node_n_messages "https://github.com/aeroxy/drift/blob/master/src/protocol/messages.rs"
click node_n_transfer_proto "https://github.com/aeroxy/drift/blob/master/src/protocol/transfer.rs"
click node_n_ws_handler "https://github.com/aeroxy/drift/blob/master/src/server/ws_handler.rs"
click node_n_file_api "https://github.com/aeroxy/drift/blob/master/src/server/file_api.rs"
click node_n_browser_transfer "https://github.com/aeroxy/drift/blob/master/src/server/browser_transfer.rs"
click node_n_transfer_receiver "https://github.com/aeroxy/drift/blob/master/src/server/transfer_receiver.rs"
click node_n_browse_fs "https://github.com/aeroxy/drift/blob/master/src/fileops/browse.rs"
click node_n_reader_writer "https://github.com/aeroxy/drift/blob/master/src/fileops/reader.rs"
click node_n_compress "https://github.com/aeroxy/drift/blob/master/src/fileops/compress.rs"
click node_n_decompress "https://github.com/aeroxy/drift/blob/master/src/fileops/decompress.rs"
click node_n_frontend_rs "https://github.com/aeroxy/drift/blob/master/src/frontend.rs"
click node_n_app "https://github.com/aeroxy/drift/blob/master/frontend/src/App.tsx"
click node_n_ws_hook "https://github.com/aeroxy/drift/blob/master/frontend/src/hooks/useWebSocket.ts"
click node_n_transfer_hook "https://github.com/aeroxy/drift/blob/master/frontend/src/hooks/useTransfer.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_n_main,node_n_config,node_n_server_mod,node_n_client_mod,node_n_reconnect toneBlue
class node_n_handshake,node_n_stream,node_n_codec,node_n_messages,node_n_transfer_proto,node_n_ws_handler toneAmber
class node_n_file_api,node_n_browser_transfer,node_n_transfer_receiver,node_n_browse_fs,node_n_reader_writer,node_n_compress,node_n_decompress toneMint
class node_n_frontend_rs,node_n_app,node_n_ws_hook,node_n_transfer_hook toneRose
```

## Components

### Runtime

CLI entrypoints and process orchestration

- [Main](https://github.com/aeroxy/drift/blob/master/src/main.rs): rust binary · Parses modes and starts server, client, or one-shot transfer flows · `src/main.rs`
- [Config](https://github.com/aeroxy/drift/blob/master/src/config.rs): cli config · Command and mode parsing for serve, send, ls, and pull · `src/config.rs`
- [Server](https://github.com/aeroxy/drift/blob/master/src/server/mod.rs): backend · HTTP/WebSocket-facing backend for local browsing and incoming transfers · `src/server/mod.rs`
- [Client](https://github.com/aeroxy/drift/blob/master/src/client/mod.rs): outbound side · Outbound peer that connects to a remote drift instance · `src/client/mod.rs`
- [Reconnect](https://github.com/aeroxy/drift/blob/master/src/client/reconnect.rs): session recovery · Re-establishes outbound sessions after disconnects · `src/client/reconnect.rs`

### Network

Encrypted WebSocket protocol and session security

- [Handshake](https://github.com/aeroxy/drift/blob/master/src/crypto/handshake.rs): x25519+kdf · Performs key exchange and derives directional session keys · `src/crypto/handshake.rs`
- [Stream Crypto](https://github.com/aeroxy/drift/blob/master/src/crypto/stream.rs): cipher framing · Encrypts and decrypts WebSocket traffic with authenticated frames · `src/crypto/stream.rs`
- [Codec](https://github.com/aeroxy/drift/blob/master/src/protocol/codec.rs): wire encoding · Encodes control messages and binary transfer frames · `src/protocol/codec.rs`
- [Messages](https://github.com/aeroxy/drift/blob/master/src/protocol/messages.rs): control schema · Defines encrypted JSON control messages and request correlation · `src/protocol/messages.rs`
- [Transfer Proto](https://github.com/aeroxy/drift/blob/master/src/protocol/transfer.rs): chunk format · Defines file chunk payloads, UUIDs, and offsets for concurrent transfer · `src/protocol/transfer.rs`
- [WS Handler](https://github.com/aeroxy/drift/blob/master/src/server/ws_handler.rs): session endpoint · Manages encrypted WebSocket sessions at the server boundary · `src/server/ws_handler.rs`

### Transfer Services

Filesystem access and transfer execution

- [File API](https://github.com/aeroxy/drift/blob/master/src/server/file_api.rs): browse api · Serves browse and file information requests over the session · `src/server/file_api.rs`
- [Browser Transfer](https://github.com/aeroxy/drift/blob/master/src/server/browser_transfer.rs): ui transfer coordinator · Coordinates UI-initiated send and pull operations · `src/server/browser_transfer.rs`
- [Receiver](https://github.com/aeroxy/drift/blob/master/src/server/transfer_receiver.rs): ingest sink · Writes incoming data and handles extraction on receipt · `src/server/transfer_receiver.rs`
- [Browse FS](https://github.com/aeroxy/drift/blob/master/src/fileops/browse.rs): path guard · Canonicalizes browse paths and prevents traversal outside the root · `src/fileops/browse.rs`
- [Chunk I/O](https://github.com/aeroxy/drift/blob/master/src/fileops/reader.rs): streamed io · Implements chunked async reads and writes for large transfers · `src/fileops/reader.rs`
- [Compress](https://github.com/aeroxy/drift/blob/master/src/fileops/compress.rs): tar.gz packer · Packages directories into archives for recursive transfer · `src/fileops/compress.rs`
- [Decompress](https://github.com/aeroxy/drift/blob/master/src/fileops/decompress.rs): tar.gz unpacker · Extracts received archives back into directories · `src/fileops/decompress.rs`

### Frontend

Embedded React UI and its bundle pipeline

- [Frontend Embed](https://github.com/aeroxy/drift/blob/master/src/frontend.rs): asset host · Serves the built frontend assets from inside the Rust binary · `src/frontend.rs`
- [App UI](https://github.com/aeroxy/drift/blob/master/frontend/src/App.tsx): react ui · Two-pane file browser with connection, path, toolbar, and progress controls · `frontend/src/App.tsx`
- [WS Hook](https://github.com/aeroxy/drift/blob/master/frontend/src/hooks/useWebSocket.ts): frontend hook · Connects the UI to backend WebSocket events · `frontend/src/hooks/useWebSocket.ts`
- [Transfer Hook](https://github.com/aeroxy/drift/blob/master/frontend/src/hooks/useTransfer.ts): frontend hook · Tracks transfer state and progress in the UI · `frontend/src/hooks/useTransfer.ts`

## Connections

- Main → Config: parses · Chooses runtime mode and transfer command
- Main → Server: starts · Launches the local server/runtime path
- Main → Client: opens · Creates outbound sessions for remote targets
- Client → Reconnect: reconnects · Restores long-lived sessions after disconnects
- Server → WS Handler: accepts · Owns the encrypted network session boundary
- WS Handler → Handshake: negotiates · Performs key exchange before application traffic
- WS Handler → Stream Crypto: encrypts · Wraps all traffic in authenticated encryption
- Stream Crypto → Codec: frames · Carries control and binary messages over the wire
- Codec → Messages: encodes · Serializes request and response control messages
- Codec → Transfer Proto: encodes · Serializes chunked file payload frames
- Server → File API: routes · Exposes browse and info operations to peers
- Server → Browser Transfer: coordinates · Handles transfer actions initiated from the UI
- Browser Transfer → Receiver: delivers · Hands off incoming content for persistence
- File API → Browse FS: validates · Restricts paths to the configured local root
- Receiver → Chunk I/O: streams · Uses chunked I/O for large file movement
- Browser Transfer → Compress: packages · Archives directories before send
- Receiver → Decompress: extracts · Unpacks directory archives after receive
- Chunk I/O → Transfer Proto: moves · Transfers file bytes in 64 KB chunks
- Frontend Embed → App UI: serves · Embeds the generated UI bundle into the binary
- App UI → WS Hook: binds · Subscribes the UI to backend session events
- App UI → Transfer Hook: binds · Displays live transfer progress and status
- Client → WS Handler: connects · Uses the same protocol on the outbound peer side
