# CLAUDE.md — Mesh Agent This file provides agent-specific guidance for the Mesh desktop agent (Rust). ## Agent Role The Mesh Agent is a desktop application (Linux/Windows/macOS) that provides: - **P2P data plane**: QUIC connections for file/folder/terminal transfer - **Local capabilities**: Terminal/PTY management, file watching - **Server integration**: WebSocket control plane, REST API - **Gotify notifications**: Direct notification sending **Critical**: The agent handles ONLY data plane via QUIC. Media (audio/video/screen) is handled by the web client via WebRTC. ## Technology Stack - **Rust stable** (edition 2021) - **tokio**: Async runtime - **quinn**: QUIC implementation - **tokio-tungstenite**: WebSocket client - **reqwest**: HTTP client - **portable-pty**: Cross-platform PTY - **tracing**: Logging framework - **thiserror**: Error types ## Project Structure ``` agent/ ├── src/ │ ├── main.rs # Entry point │ ├── config/ │ │ └── mod.rs # Configuration management │ ├── mesh/ │ │ ├── mod.rs │ │ ├── types.rs # Event type definitions │ │ ├── ws.rs # WebSocket client │ │ └── rest.rs # REST API client │ ├── p2p/ │ │ ├── mod.rs │ │ ├── endpoint.rs # QUIC endpoint │ │ └── protocol.rs # P2P protocol messages │ ├── share/ │ │ ├── mod.rs │ │ ├── file_send.rs # File transfer │ │ └── folder_zip.rs # Folder zipping │ ├── terminal/ │ │ └── mod.rs # PTY management │ └── notifications/ │ └── mod.rs # Gotify client ├── tests/ ├── Cargo.toml ├── Cargo.lock └── CLAUDE.md ``` ## Development Commands ### Setup ```bash cd agent # Install Rust if needed: https://rustup.rs/ rustup update stable ``` ### Build ```bash cargo build ``` ### Run ```bash cargo run ``` ### Build Release ```bash cargo build --release # Binary in target/release/mesh-agent ``` ### Run Tests ```bash cargo test ``` ### Format & Lint ```bash cargo fmt cargo clippy -- -D warnings ``` ## Configuration The agent creates a config file at: - **Linux**: `~/.config/mesh/agent.toml` - **macOS**: `~/Library/Application Support/Mesh/agent.toml` - **Windows**: `%APPDATA%\Mesh\agent.toml` **Config structure**: ```toml device_id = "uuid-v4" server_url = "http://localhost:8000" ws_url = "ws://localhost:8000/ws" auth_token = "optional-jwt-token" gotify_url = "optional-gotify-url" gotify_token = "optional-gotify-token" quic_port = 0 # 0 for random log_level = "info" ``` ## QUIC P2P Protocol ### Session Flow 1. **Request session** via WebSocket (`p2p.session.request`) 2. **Receive session info** (`p2p.session.created`) with endpoints and auth 3. **Establish QUIC connection** to peer 4. **Send P2P_HELLO** with session_token 5. **Receive P2P_OK** or P2P_DENY 6. **Transfer data** via QUIC streams 7. **Close session** ### First Message: P2P_HELLO Every QUIC stream MUST start with: ```json { "t": "P2P_HELLO", "session_id": "uuid", "session_token": "jwt-from-server", "from_device_id": "uuid" } ``` The peer validates the token before accepting the stream. ### Message Types **File transfer**: - `FILE_META`: name, size, hash - `FILE_CHUNK`: offset, data - `FILE_ACK`: last_offset - `FILE_DONE`: final hash **Folder transfer**: - `FOLDER_MODE`: zip or sync - `ZIP_META`, `ZIP_CHUNK`, `ZIP_DONE` (for zip mode) **Terminal**: - `TERM_OUT`: output data (UTF-8) - `TERM_RESIZE`: cols, rows - `TERM_IN`: input data (requires `terminal:control` capability) See [protocol_events_v_2.md](../protocol_events_v_2.md) for complete protocol. ## Error Handling Rules **CRITICAL**: NO `unwrap()` or `expect()` in production code. Use `Result` everywhere: ```rust use anyhow::Result; use thiserror::Error; #[derive(Error, Debug)] pub enum AgentError { #[error("WebSocket error: {0}")] WebSocket(String), #[error("QUIC error: {0}")] Quic(String), #[error("IO error: {0}")] Io(#[from] std::io::Error), } ``` Handle errors gracefully: ```rust match risky_operation().await { Ok(result) => handle_success(result), Err(e) => { tracing::error!("Operation failed: {}", e); // Attempt recovery or return error } } ``` ## Logging Use `tracing` crate: ```rust use tracing::{info, warn, error, debug}; info!("Connection established"); warn!("Retrying connection: attempt {}", attempt); error!("Failed to send file: {}", err); debug!("Received chunk: offset={}, len={}", offset, len); ``` **Never log**: - Passwords, tokens, secrets - Full file contents - Sensitive user data ## Security Checklist - [ ] All QUIC sessions validated with server-issued tokens - [ ] Tokens checked for expiration - [ ] Terminal input ONLY accepted with `terminal:control` capability - [ ] SSH secrets never transmitted (stay on local machine) - [ ] File transfers use chunking with hash verification - [ ] No secrets in logs - [ ] TLS 1.3 for all QUIC connections ## Terminal/PTY Management **Default mode**: Preview (read-only) - Agent creates PTY locally - Spawns shell (bash/zsh on Unix, pwsh on Windows) - Streams output via `TERM_OUT` messages - Ignores `TERM_IN` messages unless control granted **Control mode**: (requires server-arbitrated capability) - ONE controller at a time - Server issues `terminal:control` capability token - Agent validates token before accepting input - Input sent via `TERM_IN` messages **Important**: Can run `ssh user@host` in the PTY for SSH preview. ## File Transfer Strategy **Chunking**: - Default chunk size: 256 KB - Adjustable based on network conditions **Hashing**: - Use `blake3` for speed - Hash each chunk + final hash - Receiver validates **Resume**: - Track `last_offset` with `FILE_ACK` - Resume from last acknowledged offset on reconnect **Backpressure**: - Wait for `FILE_ACK` before sending next batch - Limit in-flight chunks ## Cross-Platform Considerations **PTY**: - Unix: `portable-pty` with bash/zsh - Windows: `portable-pty` with PowerShell or ConPTY **File paths**: - Use `std::path::PathBuf` (cross-platform) - Handle path separators correctly **Config directory**: - Linux: `~/.config/mesh/` - macOS: `~/Library/Application Support/Mesh/` - Windows: `%APPDATA%\Mesh\` ## Build & Packaging **Single binary per platform**: - Linux: `mesh-agent` (ELF) - macOS: `mesh-agent` (Mach-O) - Windows: `mesh-agent.exe` (PE) **Installers** (V1/V2): - Linux: `.deb`, `.rpm` - macOS: `.dmg`, `.pkg` - Windows: `.msi` **Release profile** (Cargo.toml): ```toml [profile.release] opt-level = 3 lto = true codegen-units = 1 strip = true ``` ## Testing Strategy 1. **Unit tests**: Individual functions, protocol parsing 2. **Integration tests**: QUIC handshake, file transfer end-to-end 3. **Manual tests**: Cross-platform PTY, real network conditions ## Performance Targets - QUIC connection establishment: < 500ms - File transfer: > 100 MB/s on LAN - Terminal latency: < 50ms - Memory usage: < 50 MB idle, < 200 MB active transfer ## Development Workflow **Iterative approach** (CRITICAL): 1. Build compilable skeleton first 2. Add one module at a time 3. Test after each module 4. NO "big bang" implementations **Module order** (recommended): 1. Config + logging 2. WebSocket client (basic connection) 3. REST client (health check, auth) 4. QUIC endpoint (skeleton) 5. File transfer (simple) 6. Terminal/PTY (preview only) 7. Gotify notifications 8. Advanced features (folder sync, terminal control) --- **Remember**: The agent is data plane only (QUIC). WebRTC media is handled by the web client. Work in short iterations, and never use `unwrap()` in production code.