README
ΒΆ
Sendy
Sendy is a peer-to-peer encrypted chat application with WebRTC connections and a terminal user interface (TUI). It provides end-to-end encryption for secure messaging and file transfers.
Features
- π End-to-End Encryption: All messages and files encrypted with NaCl/box (Curve25519 + XSalsa20-Poly1305)
- π Ed25519 Authentication: Cryptographic identity for each peer
- π P2P WebRTC Connections: Direct peer-to-peer communication after initial handshake
- π¬ Persistent Chat History: SQLite database for messages and contacts
- π Message Search: Fast full-text search across all conversations
- π File Transfer: Send files up to 200MB with encrypted transit
- π¨ Terminal UI: Modern TUI built with Bubbletea
- π High Performance: 1.27 GB/s direct P2P transfer, 63,642 msg/s router throughput
- π‘ NAT Traversal: STUN servers for connecting peers behind NAT/firewalls
- π« Contact Blocking: Block unwanted peers
- π Online Status: Real-time connection status indicators
Quick Start
Prerequisites
- Go 1.21 or later
fzf(for file picker):brew install fzf(macOS) orsudo apt install fzf(Ubuntu)
Installation
# Clone the repository
git clone https://github.com/udisondev/sendy.git
cd sendy
# Build the unified CLI
go build -o bin/sendy ./cmd/sendy
# Or use Makefile
make build
Running
β οΈ IMPORTANT: Start the router server first, then chat clients!
Step 1: Start the Router Server
./bin/sendy router
# Router starts on port 9090 by default
# Keep this terminal window open!
To use a different port:
./bin/sendy router --addr :7777
Step 2: Start Chat Clients (in new terminal windows)
# First client (default command)
./bin/sendy
# Or explicitly
./bin/sendy chat
# Second client (use different data directory)
./bin/sendy chat --data /tmp/alice
# If router is on different port
./bin/sendy chat --router localhost:7777
On first run, keys are automatically generated and your Peer ID is displayed.
Step 3: Add Contacts and Chat
- Copy your Peer ID (64 hex characters) from the startup message
- In the other client, press
ato add contact - Paste the Peer ID and press Enter
- Select the contact and press
cto connect - Wait for
[Online]status - Press
Tabto switch to input field and type your message - Press
Enterto send - Press
fto send a file (opens fzf file picker)
Usage
Keyboard Shortcuts
General:
Tab- Switch between panels (Contacts β Messages β Input)q- Quit (not available when focused on input field)
Contact List Panel (left):
β/βorj/k- Navigate contacts/- Search and filter contacts by namea- Add new contacti- Show your Peer IDd- Delete contact and chat historyb- Block/unblock contactc- Connect to selected contactx- Disconnect from selected contact
Message Panel (top right):
β/βorj/k- Scroll messages/- Search messages across all conversationsPgUp/PgDown- Page through messages
Input Panel (bottom right):
- Type your message (multi-line supported)
Enter- New lineCtrl+S- Send messagef- Send file (opens fzf file picker)Esc- Cancel file selection
Contact Search Mode:
/- Open contact search (from contact list panel)- Type contact name and press
Enterto filter β/βorj/k- Navigate filtered contactsEnter- Select contact and open chatEsc- Close search and return to main view
Message Search Mode:
/- Open message search (from message panel)- Type your search query and press
Enterto search β/βorj/k- Navigate search resultsEnter- Jump to selected message in conversationEsc- Close search and return to main view
Data Directory
By default, all data is stored in ~/.sendy/:
~/.sendy/
βββ logs/
β βββ router/
β β βββ router-*.log # Router logs
β βββ chat/
β βββ chat-*.log # Chat logs
βββ data/
βββ key # Ed25519 private key (protect this!)
βββ chat.db # SQLite database
βββ files/ # Received files
To use a custom directory:
./bin/sendy --data /path/to/data
Generating New Keys
# Generate and display new keypair without starting chat
./sendy chat --genkey
Architecture
ββββββββββββ ββββββββββββ
β Alice β β Bob β
β (Client) β β (Client) β
ββββββ¬ββββββ βββββββ¬βββββ
β β
β WebRTC Signaling β
β (encrypted) β
ββββββββββ¬βββββββββββββ
β
ββββββΌββββββ
β Router β
β Server β
ββββββββββββ
β
After connection:
β
βββββββββββββββΌβββββββββββββββ
β Direct P2P Connection β
β (End-to-End Encrypted) β
β Alice βββββββ Bob β
ββββββββββββββββββββββββββββββ
Components
-
Router Server (
router/)- Central signaling server for WebRTC handshake
- Ed25519 authentication
- Zero-copy I/O with
sync.Pool - Does not see message content (only metadata)
-
P2P Connector (
p2p/)- WebRTC peer-to-peer connections
- Perfect negotiation for collision resolution
- End-to-end encryption for all data
- Contact blocklist management
-
Chat (
chat/)- Message handling and persistence
- Contact management
- File transfer coordination
- SQLite storage
-
TUI (
chat/tui.go)- Terminal interface built with Bubbletea
- Contact list with online status
- Message history view
- File picker integration (fzf)
Security
Sendy implements end-to-end encryption for all peer-to-peer communications. For detailed security information, see SECURITY.md.
Highlights
- Authentication: Ed25519 digital signatures (256-bit security)
- Encryption: NaCl/box (Curve25519 + XSalsa20-Poly1305)
- Trust Model: TOFU (Trust On First Use)
- Protection: Messages, files, and WebRTC signaling are all encrypted
Known Limitations
β οΈ Please read before use:
- No Perfect Forward Secrecy (PFS) - compromise of private key affects past messages
- MITM vulnerability on first connection (TOFU model)
- Router sees connection metadata (not content)
- No key rotation
See SECURITY.md for complete security documentation.
Performance
Router (Signaling):
- 63,642 messages/sec (2 peers)
- 17.73 ns/op
- 24 B/op, 1 allocs/op
WebRTC P2P Transfer:
- 1.27 GB/s direct transfer
- 803.7 ns/op
- No server involvement after connection
Configuration
Router Server
./bin/sendy router --addr :9090 # Listen address
./bin/sendy router --logdir logs # Log directory
Chat Client
./bin/sendy --router localhost:9090 # Router address
./bin/sendy --data ~/.sendy # Data directory
./bin/sendy --genkey # Generate keys only
./bin/sendy --stun-servers "stun:my.server:3478,stun2:port" # Custom STUN servers
Available Commands
sendy # Start chat client (default)
sendy chat # Start chat client
sendy router # Start router server
sendy --help # Show help
sendy chat --help # Show chat options
sendy router --help # Show router options
Environment Variables
DEBUG=1- Enable debug loggingSENDY_STUN_SERVERS- Comma-separated list of STUN servers (e.g.,stun:stun.l.google.com:19302,stun:stun.cloudflare.com:3478)
STUN Server Configuration
STUN servers are used for NAT traversal to establish P2P connections. Priority order:
--stun-serversflag (highest priority)SENDY_STUN_SERVERSenvironment variable- Default servers (Google, Cloudflare, Twilio)
Default STUN servers:
stun:stun.l.google.com:19302 # Google (reliable, ~0.15s)
stun:stun1.l.google.com:19302 # Google backup
stun:stun.cloudflare.com:3478 # Cloudflare (fastest, ~0.05s)
stun:global.stun.twilio.com:3478 # Twilio (production-ready, ~0.17s)
Examples:
# Use custom STUN servers via flag
./bin/sendy --stun-servers "stun:mystun.example.com:3478,stun:backup.example.com:3478"
# Use custom STUN servers via environment
export SENDY_STUN_SERVERS="stun:mystun.example.com:3478,stun:backup.example.com:3478"
./bin/sendy
# Use default servers (no flag or env set)
./bin/sendy
Note: Different peers can use different STUN servers without issues. Each peer uses STUN servers independently to discover their own public IP address.
Limits
MaxFileSize = 200 MB // Maximum file transfer size
MaxMessageSize = 10 MB // Maximum message size
MaxContactName = 256 bytes // Maximum contact name length
MaxContactCount = 10000 // Maximum contacts per user
Project Structure
sendy/
βββ cmd/
β βββ sendy/ # Unified CLI application
β βββ main.go # Entry point
β βββ cmd/ # Cobra commands
β βββ root.go # Root command
β βββ chat.go # Chat client command
β βββ router.go # Router server command
βββ router/ # Router server and client
β βββ router.go # Server implementation
β βββ client.go # Client library
β βββ types.go # Protocol types
β βββ const.go # Constants
βββ p2p/ # WebRTC P2P connector
β βββ webrtc.go # Connection management
β βββ crypto.go # End-to-end encryption
β βββ *_test.go # Tests
βββ chat/ # Chat logic
β βββ chat.go # Core chat logic
β βββ storage.go # SQLite persistence
β βββ tui.go # Bubbletea TUI
β βββ filepicker_external.go # fzf integration
βββ SECURITY.md # Security documentation
βββ LICENSE # MIT License
βββ README.md # This file
Development
Building
# Build unified CLI
go build -o bin/sendy ./cmd/sendy
# Build with debug symbols stripped (smaller binary)
go build -ldflags="-s -w" -o bin/sendy ./cmd/sendy
# Or use Makefile
make build # Normal build
make build-release # Optimized build
make clean # Clean build artifacts
Testing
# Run all tests
go test ./...
# Test specific package
go test ./router
go test ./p2p
go test ./chat
# Run with verbose output
go test -v ./...
# Run benchmarks
go test -bench=. -benchtime=5s ./router
go test -bench=. -benchtime=5s ./p2p
Running Tests with Real Peers
# Terminal 1: Start router
./sendy router
# Terminal 2: Start Alice
./sendy chat --data /tmp/alice
# Terminal 3: Start Bob
./sendy chat --data /tmp/bob
# Add each other as contacts and test messaging/file transfer
Roadmap
Security Improvements:
- Perfect Forward Secrecy (PFS) implementation
- Key rotation support
- Optional key encryption with passphrase
- Multi-device key synchronization
Features:
- Message search
- Group chats
- Voice/video calls (WebRTC media streams)
- Message reactions and replies
- Contact verification (QR codes)
- Desktop notifications
UX Improvements:
- File transfer progress bars
- Image preview in terminal
- Emoji support
- Customizable themes
- Message timestamps in chat view
Operations:
- Configurable STUN/TURN servers
- Docker images
- systemd service files
- Configuration file support
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Before contributing:
- Read SECURITY.md to understand the security model
- Ensure all tests pass:
go test ./... - Add tests for new features
- Follow Go best practices and conventions
- Update documentation as needed
Dependencies
- spf13/cobra - CLI framework
- pion/webrtc - WebRTC implementation
- charmbracelet/bubbletea - TUI framework
- mattn/go-sqlite3 - SQLite driver
- golang.org/x/crypto - Cryptographic primitives
License
MIT License - see LICENSE file for details.
Acknowledgments
- Built with Pion WebRTC
- UI powered by Charm Bracelet's Bubbletea
- Cryptography from NaCl/box and Go's crypto libraries
β οΈ Security Notice: Sendy is experimental software. While it implements strong cryptography, it has not undergone a professional security audit. Use at your own risk. See SECURITY.md for details.
Documentation
ΒΆ
There is no documentation for this package.
Directories
ΒΆ
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
sendy
command
|
|
|
Package p2p ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ WebRTC P2P ΠΊΠΎΠ½Π½Π΅ΠΊΡΠΎΡ Π΄Π»Ρ ΠΏΡΡΠΌΠΎΠ³ΠΎ ΠΎΠ±ΠΌΠ΅Π½Π° Π΄Π°Π½Π½ΡΠΌΠΈ ΠΌΠ΅ΠΆΠ΄Ρ ΠΏΠΈΡΠ°ΠΌΠΈ.
|
Package p2p ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ WebRTC P2P ΠΊΠΎΠ½Π½Π΅ΠΊΡΠΎΡ Π΄Π»Ρ ΠΏΡΡΠΌΠΎΠ³ΠΎ ΠΎΠ±ΠΌΠ΅Π½Π° Π΄Π°Π½Π½ΡΠΌΠΈ ΠΌΠ΅ΠΆΠ΄Ρ ΠΏΠΈΡΠ°ΠΌΠΈ. |