Files
mesh/agent/CLAUDE.md
Gilles Soulier 1d177e96a6 first
2026-01-05 13:20:54 +01:00

7.7 KiB

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

cd agent
# Install Rust if needed: https://rustup.rs/
rustup update stable

Build

cargo build

Run

cargo run

Build Release

cargo build --release
# Binary in target/release/mesh-agent

Run Tests

cargo test

Format & Lint

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:

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:

{
  "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 for complete protocol.

Error Handling Rules

CRITICAL: NO unwrap() or expect() in production code.

Use Result<T, E> everywhere:

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:

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:

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):

[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.