A cross-platform, no-registration LAN chat app with file transfer support.
📖 中文文档
- 🚀 No Registration - Auto-generates random usernames; click to change anytime
- 💻 Cross-Platform - Linux desktop, Windows desktop, Android App, Web
- 🔍 Auto Discovery - UDP broadcast/multicast based LAN device discovery
- 🔗 Manual Discovery - Add by IP, domain, or hostname; works across VLANs / WireGuard
- 🔄 Smart Reply - Auto-replies to heartbeats; only one side needs to add the other for mutual discovery
- 💬 Real-time Chat - Text messages, streaming messages, and file transfer
- 📁 File Transfer - Large file chunked transfer with configurable auto-accept
- 📸 Image Preview - Automatic preview for image messages
- 💾 History - SQLite database for chat history
- 🔧 Port Config - Customizable service port in settings, overridable via CLI
- 📂 Database Path - Custom database location, persisted in config file
- 🌐 Web Client - Deployable on headless servers
- 🔔 System Notifications - Linux desktop, Windows desktop, Android App, Web
- 💡 Tray Icon Flash - Click to jump to latest unread; right-click menu to toggle notifications
- 🌍 i18n - Automatic system language detection, manual switch, tray menu hot-reload
- 🤖 LANClaw AI Bot - Pi-powered AI chatbot with auto-reply, file analysis, and scheduled tasks
- 📱 Android Dual-Track File Engine — SAF persistable permissions + Share Intent FD cache zero-copy dual track
- 📁 SAF File Picker — Android native
ACTION_OPEN_DOCUMENT; selected files remain readable across process/reboot - 🔁 Offline Re-send — Offline messages auto-cached; auto-re-send on reconnect, including files
- 🔗 Manual Receive - Turn off Auto Download and click to download files manually
paru -S lanchat-binhttps://github.com/cap153/LANChat/releases
Prerequisites:
https://v2.tauri.app/start/prerequisites/
# Desktop Linux
cargo tauri build --bundles deb
cargo tauri build --bundles rpm
# Android APK
cargo tauri android build --target aarch64
./sign-apk.sh
# Windows desktop
cd src-tauri
cargo xwin build --release --bin lanchat --target x86_64-pc-windows-msvc
# Web (lightweight, no GUI dependencies)
cd src-tauri
cargo build --release --bin lanchat-web --features web --no-default-features
cargo build --no-default-features --features web --release --target x86_64-pc-windows-gnu # Windows webOr use the Makefile for one-click builds:
make all # Build all tested platforms
make deb # Linux .deb
make rpm # Linux .rpm
make apk # Android APK (auto-signed)
make windows-desktop # Windows desktop (requires cargo-xwin)
make web # Web (Linux)
make web-windows # Web (Windows)
make help # Show help- Start the service (default port
8888, configurable in settings):
# Desktop
lanchat
# Web
lanchat-webCLI arguments --port and --db-path override config file settings with highest priority.
# Web / Desktop
lanchat --port 8889 --db-path /custom/path/lanchat.dbTip
Run multiple instances by specifying different ports and database paths.
Use the Add panel with <IP>:<port> to discover across ports.
Once one side receives a heartbeat, the reply mechanism enables mutual discovery.
- Firewall configuration (ufw example):
Important
Ensure both TCP and UDP are allowed for the configured port.
# TCP: Web pages and WebSocket communication
sudo ufw allow 8888/tcp
# UDP: Device discovery (broadcast/multicast/heartbeat)
sudo ufw allow 8888/udpPlace custom .css files in the config directory (any filename):
- Linux:
~/.config/lanchat/ - Windows:
%APPDATA%\.config\lanchat
See built-in themes for reference: https://github.com/cap153/LANChat/tree/main/src/css
Port, language, and other settings are stored in config.json. CLI arguments --port and --db-path take highest priority.
- Linux:
~/.config/lanchat/config.json - Windows:
%APPDATA%\lanchat\config.json - macOS:
~/Library/Application Support/lanchat/config.json
Example content:
{
"db_path": null,
"port": 8888,
"lang": "en"
}| Field | Description |
|---|---|
db_path |
Database path; null = default |
port |
Listening port, default 8888 |
lang |
Interface language: zh (Chinese), en (English) |
Desktop and Web share the same database:
- Linux:
~/.local/share/com.lanchat.app/lanchat.db - Windows:
%APPDATA%\com.lanchat.app\lanchat.db
The database path can be changed in settings (requires restart). The path is stored in ~/.config/lanchat/config.json.
- Auto-generated random usernames
- Click username to rename
- LAN device discovery (UDP broadcast/multicast)
- Real-time online user list
- Standalone Web deployment
- Shared database between desktop and Web
- Settings panel (port, db path, download path)
- Chat history query
- Theme switching
- Android support
- Text message transfer
- File transfer
- Windows support
- Single instance lock
- Streaming file transfer
- Dynamic chunk size based on system memory
- Broadcast and multicast support
- Android hotspot random subnet brute-force
- Web: click file message to download directly
- Desktop: click file message to open containing folder
- Android: receive shared files from other apps and send
- Android: share file messages to other apps
- Desktop & Web: drag-and-drop file sending
- Desktop: paste file sending (zero-copy, Wayland-first)
- Web: paste file sending
- Auto image preview
- Red dot for unread messages
- Lazy-load history (scroll to trigger)
- Delete chat history
- Android: open file messages
- Smart file deduplication (reuse identical files, auto-rename on conflict)
- Offline message re-send on reconnect
- Clipboard image paste sending
- Delete offline users
- Clear chat history
- Android: status bar / navigation bar adaptation
- LANClaw streaming AI replies
- Model switching command (
/model) - New session command (
/new) - Manual discovery (IP / domain / hostname, cross-VLAN / WireGuard)
- UDP heartbeat auto-reply (cross-port / cross-subnet auto discovery)
- System notifications (desktop: PowerShell / notify-send, Web: Notification API, Android: native)
- Tray icon flash (unread notification, click to jump to latest)
- Notification toggle (tray right-click menu, desktop only)
- Manual file receive
- Android SAF persistable permissions + zero-copy FD cache dual-track
- Android SAF native file picker (
ACTION_OPEN_DOCUMENT+takePersistableUriPermission) - Real-time file transfer speed display
- Platform-standard config paths (Linux
~/.config/, Windows%APPDATA%) - i18n (auto-detect + manual switch + tray hot-reload)
- Group chat
- Better default icon
LANChat/
├── src/ # Frontend
│ ├── css/
│ │ ├── style.css # Main stylesheet
│ │ └── vscode.css # VSCode theme
│ ├── js/
│ │ ├── api.js # API wrapper (Tauri + HTTP dual backend)
│ │ ├── app.js # App logic
│ │ └── ui.js # UI interactions
│ └── index.html # Main page
├── src-tauri/ # Backend (desktop + Web)
│ ├── src/
│ │ ├── main.rs # Desktop Tauri entry
│ │ ├── server_main.rs # Web standalone entry
│ │ ├── lib.rs # Android entry
│ │ ├── commands.rs # Tauri commands
│ │ ├── web_server.rs # HTTP/WebSocket server
│ │ ├── db.rs # SQLite database logic
│ │ ├── config_file.rs # Config file read/write
│ │ ├── peers.rs # Online user manager
│ │ ├── models.rs # Data models
│ │ ├── utils.rs # Utilities
│ │ └── network/ # Network module
│ │ ├── discovery.rs # UDP device discovery
│ │ └── messaging.rs # WebSocket messaging
│ ├── capabilities/ # Tauri capability config
│ ├── permissions/ # Custom command permissions
│ └── Cargo.toml
├── Makefile # One-click build
└── README.md # This file
| Role | Status Value | Display Text |
|---|---|---|
| Sender | status: "pending" |
pending |
| Sender | file_status: "offering" |
offering |
| Sender | file_status: "uploading" |
xx MB/s |
| Sender | file_status: "sent" |
(empty) |
| Receiver | file_status: "offered" |
offered |
| Receiver | file_status: "invalid" |
invalid |
| Receiver | file_status: "downloading" |
xx MB/s |
| Receiver | file_status: "accepted" |
(empty) |
Windows: missing VCRUNTIME140.dll / VCRUNTIME140_1.dll:
https://aka.ms/vs/17/release/vc_redist.x64.exe
https://aka.ms/vs/17/release/vc_redist.x86.exe
Windows: WebView2 not installed:
https://developer.microsoft.com/en-us/microsoft-edge/webview2
Online user sends messages but they show as Pending on my side:
Disable mobile data / VPN and reconnect to WiFi.
NVIDIA graphics card not rendering correctly on Linux desktop:
Add the environment variable Exec=env __NV_DISABLE_EXPLICIT_SYNC=1 lanchat to the desktop file.
Cross-VLAN / WireGuard:
When devices are on different VLANs or connected via WireGuard, UDP broadcast won't cross subnets. Solution: use the Add panel to enter the peer's IP/domain/hostname with port. The system sends unicast heartbeats periodically (DNS resolution supported, 60s cache).
Tip
Only one side needs to add the other. Upon receiving a heartbeat, the peer auto-replies with its own heartbeat, enabling mutual discovery without manual setup on both sides.
Reply heartbeats include a |1 marker to prevent infinite loops.
- Backend: Rust + Tauri 2.0
- Frontend: Vanilla HTML + CSS + JavaScript
- Database: SQLite (sqlx)
- Network: UDP broadcast/multicast + TCP/WebSocket + HTTP chunked upload
- Web Server: Axum
- AI Bot: LANClaw (separate process, driven by Pi RPC)
MIT License
If you find this project helpful, feel free to buy me a coffee ☕️
