322 lines
7.7 KiB
Markdown
322 lines
7.7 KiB
Markdown
# 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<T, E>` 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.
|