A lightweight terminal chat with separate server and client binaries, real-time messaging over WebSockets, optional end-to-end encryption, and a flexible plugin ecosystem. Built for developers who prefer the command line and want reliable, self-hosted group chat with minimal operational overhead.
- Overview
- Features
- Database Schema
- Installation & Setup
- Quick Start
- Configuration
- Admin Panel
- TLS Support
- Plugin System
- Ban History Gaps
- Usage
- Security
- Troubleshooting
- Roadmap
- Getting Help
- Testing
- Contributing
- Appreciation
marchat started as a fun weekend project for father-son coding sessions and has since evolved into a lightweight, self-hosted terminal chat application designed specifically for developers who love the command line. It currently runs with a local SQLite database and real-time messaging over WebSockets, with planned support for PostgreSQL and MySQL to enable greater scalability and flexibility.
Key Benefits:
- Self-hosted: No external services required
- Cross-platform: Runs on Linux, macOS, and Windows
- Secure: Optional E2E encryption with X25519/ChaCha20-Poly1305, including global encryption for public channels
- Extensible: Plugin ecosystem for custom functionality
- Lightweight: Minimal resource usage, perfect for servers
Feature | Description |
---|---|
Terminal UI | Beautiful TUI built with Bubble Tea |
Real-time Chat | Fast WebSocket-based messaging with a lightweight SQLite backend |
Plugin System | Install and manage plugins via remote registry with :store and :plugin commands |
E2E Encryption | Optional X25519 key exchange with ChaCha20-Poly1305, global encryption for public channels |
File Sharing | Send files (configurable max; default 1MB) with :sendfile and interactive picker |
Admin Controls | User management, bans, and database operations with improved ban/unban experience |
Bell Notifications | Audio alerts for new messages with :bell and :bell-mention commands |
Themes | Choose from system (default), patriot, retro, or modern themes |
Docker Support | Containerized deployment with security features |
Enhanced Security | Admin user management with ban/kick system and security logging |
Health Monitoring | Comprehensive health check endpoints (/health , /health/simple ) with system metrics |
Structured Logging | JSON-structured logging with component separation and user tracking |
Cross-Platform File Sharing | Theme Switching |
---|---|
![]() |
![]() |
marchat running on Android via Termux, demonstrating file transfer through reverse proxy and real-time theme switching
Admin commands for user management and system operations:
:cleardb # Clear all messages from database
:ban username # Permanently ban user
:kick username # Temporarily kick user (24h)
:unban username # Remove permanent ban
:allow username # Override kick early
Monitor system health with comprehensive endpoints:
# Full health check with detailed metrics
curl http://localhost:8080/health
# Simple health check for load balancers
curl http://localhost:8080/health/simple
Health check includes:
- Overall system status (healthy/degraded/unhealthy)
- Component health (database, websocket, memory)
- Performance metrics (memory usage, goroutines, active users)
- Uptime and version information
All logs are now in JSON format with component separation:
{
"level": "INFO",
"timestamp": "2024-01-15T10:30:00Z",
"component": "Server",
"user_id": "alice",
"message": "User connected",
"data": {"additional": "context"}
}
Component loggers:
- ServerLogger: Server operations
- ClientLogger: Client connections
- AdminLogger: Admin commands
- SecurityLogger: Security events
- FilterLogger: Message filtering
- DatabaseLogger: Database operations
- PluginLogger: Plugin management
- Test Suite Foundation: Added comprehensive test suite covering core packages and plugin system
- Cross-Platform Testing: Fixed Windows file path handling and cross-platform compatibility issues
- Plugin System Testing: Enhanced plugin store, manager, and host testing with proper error handling
- Documentation Updates: Updated testing documentation with realistic coverage metrics (~15% overall)
- Admin Panel Improvements: Enhanced web panel metrics display with proper alignment and formatting
- Dependency Updates: Updated SQLite dependency to v1.39.0 for improved performance and security
- Community Recognition: Added Terminal Trove to appreciation section
- Advanced Security Hardening: Implemented comprehensive rate limiting and session cleanup mechanisms
- Session Management: Automatic cleanup of expired sessions and failed login attempt tracking
- Enhanced Monitoring: Detailed security event logging with IP-based attempt tracking
- Production Security: Constant-time admin key validation and robust session lifecycle management
- Performance Optimization: Efficient session cleanup with configurable intervals
- Enhanced Authentication Security: Added rate limiting and constant-time validation for admin login
- Brute Force Protection: Maximum 5 login attempts per 15 minutes per IP address
- Security Monitoring: Comprehensive logging of authentication events and failed attempts
- Timing Attack Prevention: Constant-time admin key comparison using HMAC validation
- Proxy Support: Proper IP detection with X-Forwarded-For header support
- Comprehensive Security Fixes: Removed legacy URL parameter authentication and implemented CSRF protection
- CSRF Protection: All state-changing operations now require valid CSRF tokens for security
- Enhanced Session Security: Server-side session validation with 1-hour expiration and restricted cookie paths
- Secure Authentication Flow: Proper session-based authentication with no admin key exposure
- Secure Login System: Replaced URL-based admin key authentication with secure session-based login
- Session Cookies: HMAC-signed session tokens with 2-hour expiration and secure cookie settings
- Login Page: Clean, modern login interface that eliminates admin key exposure in URLs
- Enhanced Security: HttpOnly cookies, SameSite protection, and HTTPS-only secure flags
- Backward Compatibility: Legacy
?key=
parameter authentication still supported as fallback
- Web Admin Panel: New browser-based admin interface accessible at
/admin
with--web-panel
flag - Embedded HTML: Admin panel HTML embedded using
go:embed
for single-binary deployment - Real-time Dashboard: Live system stats, user management, plugin controls, and metrics visualization
- API Endpoints: RESTful APIs for all admin operations with
X-Admin-Key
authentication - Documentation: Comprehensive web panel setup and access instructions
- Removed Confirmation Prompts: Simplified admin command flow; hotkeys/text work consistently with E2E enabled.
- Admin Panel Live Config: Panel reads live
*config.Config
with improved TLS/status display. - Hotkey Launch Update: Admin panel launched using live config; safer terminal raw-mode handling.
- Security Cleanup: Removed
server/admin_security.go
and all confirmation wiring.
- Configurable File Size Limit: File message size can now be configured via
MARCHAT_MAX_FILE_BYTES
orMARCHAT_MAX_FILE_MB
(default 1MB). - Aligned WebSocket Read Limit: Server read limit scales with the configured max file size for consistent behavior.
- Client Enforcement: Both file picker and
:sendfile <path>
enforce the configured limit. - Plugin Host Fix: Improved executable resolution to only use
.exe
on Windows. - Documentation Updates: README updated with new environment variables and version references.
- Build & Installer Updates: Build scripts and installers updated for
v0.7.0-beta.1
. - Protocol Update: PROTOCOL file updated to reflect configurable file size.
- Enhanced Code Editor: Added copy, paste, cut, and select all keybinds to
:code
mode with visual text selection. - Clipboard Integration: System clipboard support for copy/paste operations.
- Multi-Line Selection: Added multi-line text selection support with highlighting.
- Documentation Updates: Version references and install scripts updated for
v0.6.0-beta.4
.
- Improved Admin Panel: Fixed scrolling and UI display issues with a more responsive layout.
- Interactive File Picker: Added a file browser interface for
:sendfile
with directory navigation and file type filtering. - Hyperlink Detection: Messages now auto-detect URLs with clickable links.
- Bell Notifications: Added
:bell
and:bell-mention
commands for audio alerts with config persistence.
- Server Admin Panel: New
--admin-panel
flag enables built-in terminal admin panel with Ctrl+A hotkey access. - Fixed Allow Command: Resolved
:allow
command issues with E2E encryption by implementing hotkey alternatives. - Key Binding Improvements: Changed allow command hotkey from Ctrl+A to Ctrl+Shift+A to resolve conflicts.
- Enhanced Documentation: Updated README with comprehensive admin panel documentation and E2E encryption notes.
- Admin UI with Hotkeys: New
:admin
command opens full-screen admin panel with hotkey navigation (Tab/Shift+Tab, Enter, Esc) - Code Snippet Interface: New
:code
command opens syntax-highlighted code snippet composer with language selection and live preview - Enhanced Configuration System: Improved interactive setup with connection profiles, auto-connect, and quick-start options
- Optimized Performance: Removed Glamour dependency for faster syntax highlighting using Chroma directly
- Better User Experience: Full-screen modals for admin and code features, improved navigation and error handling
- Cross-Platform Improvements: Better Windows compatibility and platform-appropriate configuration directories
- Stale Connection Management: Automatic cleanup of dead connections every 5 minutes with WebSocket ping health checks
- Enhanced Admin Commands: Added
:cleanup
and:forcedisconnect <username>
for manual stale connection removal - Restructured Moderation System:
:ban
now permanent until unban,:kick
for 24h temp ban,:allow
to override kicks early - Admin-Only Plugin Installation: Plugin installation now requires admin privileges for improved security
- Windows Terminal Fix: Fixed
--quick-start
flag freezing on Windows by implementing Bubble Tea UI for profile selection - Improved Documentation: Comprehensive troubleshooting section and moderation system documentation
- Interactive Configuration UI: Modern Bubble Tea-based form interface with styled colors, tab navigation, and real-time validation
- System Theme as Default: New "system" theme respects terminal colors for better accessibility and out-of-box experience
- Duplicate Username Detection: Intelligent error handling prevents connection loops when username is already taken
- Simplified E2E Encryption: Removed individual encryption complexity, now supports global encryption only for easier deployment
- Enhanced User Experience: Conditional field visibility, password masking, and helpful prompts in configuration UI
- Connection Profile Management: Save and manage multiple server connections with platform-appropriate storage
- Quick Start Options:
--auto
and--quick-start
flags for instant connection to saved profiles - Improved Error Handling: Clear error messages for duplicate usernames, connection failures, and configuration issues
- Backward Compatibility: All existing command-line flags continue to work as before
- Fixed Plugin Checksum Validation: Corrected plugin installation checksum validation to properly validate downloaded ZIP files instead of extracted binaries
- Enhanced Help System: Improved help overlay formatting with better spacing and removed deprecated individual E2E encryption commands
- Backward Compatibility: Added keystore location compatibility for existing users while supporting platform-appropriate directories
- Documentation Updates: Removed individual E2E encryption references from README, focusing on global encryption only
- Bug Fixes: Fixed linting errors, capitalization issues, and improved overall code quality
The database includes these key tables:
- messages: Core message storage with
message_id
for tracking - user_message_state: Per-user message history state
- ban_history: Ban/unban event tracking for history gaps feature
Download pre-built binaries for v0.8.0-beta.1:
# Linux (amd64)
wget https://github.com/Cod-e-Codes/marchat/releases/download/v0.8.0-beta.1/marchat-v0.8.0-beta.1-linux-amd64.zip
unzip marchat-v0.8.0-beta.1-linux-amd64.zip
chmod +x marchat-server marchat-client
# macOS (amd64)
wget https://github.com/Cod-e-Codes/marchat/releases/download/v0.8.0-beta.1/marchat-v0.8.0-beta.1-darwin-amd64.zip
unzip marchat-v0.8.0-beta.1-darwin-amd64.zip
chmod +x marchat-server marchat-client
# Windows (amd64)
# PowerShell (recommended):
iwr -useb https://raw.githubusercontent.com/Cod-e-Codes/marchat/main/install.ps1 | iex
# Or manual download:
wget https://github.com/Cod-e-Codes/marchat/releases/download/v0.8.0-beta.1/marchat-v0.8.0-beta.1-windows-amd64.zip
# Extract and run marchat-server.exe and marchat-client.exe from PowerShell or CMD
# Android/Termux (arm64)
pkg install wget unzip
wget https://github.com/Cod-e-Codes/marchat/releases/download/v0.8.0-beta.1/marchat-v0.8.0-beta.1-android-arm64.zip
unzip marchat-v0.8.0-beta.1-android-arm64.zip
chmod +x marchat-server marchat-client
Pull from Docker Hub:
# Latest release
docker pull codecodesxyz/marchat:v0.8.0-beta.1
# Run with environment variables
docker run -d \
-p 8080:8080 \
-e MARCHAT_ADMIN_KEY=$(openssl rand -hex 32) \
-e MARCHAT_USERS=admin1,admin2 \
codecodesxyz/marchat:v0.7.0-beta.2
Prerequisites:
- Go 1.23+ (download)
- For Linux clipboard support:
sudo apt install xclip
(Ubuntu/Debian) orsudo yum install xclip
(RHEL/CentOS)
Build from source:
git clone https://github.com/Cod-e-Codes/marchat.git
cd marchat
go mod tidy
go build -o marchat-server ./cmd/server
go build -o marchat-client ./client
chmod +x marchat-server marchat-client
For security, generate a strong random key to use as your admin key. This step is recommended but you can set any non-empty string as the admin key.
openssl rand -hex 32
# Set environment variables
export MARCHAT_ADMIN_KEY="your-generated-key"
export MARCHAT_USERS="admin1,admin2"
# Start server
./marchat-server
# Or start with admin panel enabled
./marchat-server --admin-panel
# Connect as admin
./marchat-client --username admin1 --admin --admin-key your-generated-key --server ws://localhost:8080/ws
# Connect as regular user
./marchat-client --username user1 --server ws://localhost:8080/ws
Variable | Required | Default | Description |
---|---|---|---|
MARCHAT_ADMIN_KEY |
Yes | - | Admin authentication key |
MARCHAT_USERS |
Yes | - | Comma-separated admin usernames |
MARCHAT_PORT |
No | 8080 |
Server port |
MARCHAT_DB_PATH |
No | ./config/marchat.db |
Database file path |
MARCHAT_LOG_LEVEL |
No | info |
Log level (debug, info, warn, error) |
MARCHAT_CONFIG_DIR |
No | Auto-detected | Custom config directory |
MARCHAT_TLS_CERT_FILE |
No | - | Path to TLS certificate file |
MARCHAT_TLS_KEY_FILE |
No | - | Path to TLS private key file |
MARCHAT_BAN_HISTORY_GAPS |
No | true |
Enable ban history gaps (prevents banned users from seeing messages during ban periods) |
MARCHAT_PLUGIN_REGISTRY_URL |
No | GitHub registry | URL for plugin registry (default: https://raw.githubusercontent.com/Cod-e-Codes/marchat-plugins/main/registry.json) |
MARCHAT_GLOBAL_E2E_KEY |
No | - | Base64-encoded 32-byte global encryption key for public channels |
MARCHAT_MAX_FILE_BYTES |
No | 1048576 |
Maximum file size in bytes for file messages (takes precedence) |
MARCHAT_MAX_FILE_MB |
No | - | Maximum file size in megabytes (used if bytes unset) |
Create config.json
for client configuration:
{
"username": "your-username",
"server_url": "ws://localhost:8080/ws",
"theme": "system",
"twenty_four_hour": true
}
marchat includes a built-in terminal-based admin panel that provides a comprehensive interface for server management. The admin panel allows you to monitor server statistics, manage users, configure plugins, and perform administrative tasks directly from the terminal.
Start the server with the --admin-panel
flag to enable the admin panel:
./marchat-server --admin-panel
When the admin panel is enabled, you'll see an additional message in the server startup banner:
🖥️ Admin Panel: Press Ctrl+A to open admin panel, Ctrl+C to shutdown
Once the server is running with the admin panel enabled:
- Open Admin Panel: Press
Ctrl+A
to launch the admin panel interface - Navigate: Use arrow keys to navigate through different sections
- Exit: Press
q
orEsc
to return to the server console - Shutdown: Press
Ctrl+C
to gracefully shutdown the server
The admin panel provides access to:
- Server Statistics: Real-time monitoring of connected users, message counts, and system performance
- User Management: View connected users, manage bans, and handle user permissions
- Plugin Management: Install, configure, and manage server plugins
- System Configuration: View and modify server settings
- Database Management: Access database statistics and perform maintenance tasks
- The admin panel requires a terminal environment (stdin must be a terminal)
- If running in a non-terminal environment (like systemd services), the admin panel will be automatically disabled with a warning message
- The admin panel uses terminal raw mode for hotkey detection, which is automatically restored when exiting
A browser-based admin panel is also available with secure session-based authentication.
- Enable: start the server with
--web-panel
../marchat-server --web-panel
- Access: open your browser to:
- Default HTTP:
http://localhost:8080/admin
- Custom port:
http://localhost:YOUR_PORT/admin
- TLS enabled:
https://localhost:YOUR_PORT/admin
- Default HTTP:
- Authentication: enter your admin key on the login page for secure session-based access
- Session security: 1-hour expiration with HttpOnly cookies and HTTPS-only secure flags
- CSRF protection: all admin actions protected against cross-site request forgery
- Health/API check:
curl -H "Cookie: admin_session=YOUR_SESSION_TOKEN" http://localhost:8080/admin/api/overview
TLS (Transport Layer Security) enables secure WebSocket connections using wss://
instead of ws://
. This is essential for production deployments and when exposing the server over the internet.
- Public deployments: When the server is accessible from the internet
- Production environments: For enhanced security and privacy
- Corporate networks: When required by security policies
- HTTPS reverse proxies: When behind nginx, traefik, or similar
TLS is optional but recommended for secure deployments. To enable TLS:
- Obtain SSL/TLS certificates (self-signed for testing, CA-signed for production)
- Set environment variables:
export MARCHAT_TLS_CERT_FILE="/path/to/cert.pem" export MARCHAT_TLS_KEY_FILE="/path/to/key.pem"
- Start the server - it will automatically detect TLS configuration
With TLS (recommended for production):
# Generate self-signed certificate for testing
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
# Set environment variables
export MARCHAT_ADMIN_KEY="your-secure-key"
export MARCHAT_USERS="admin1,admin2"
export MARCHAT_TLS_CERT_FILE="./cert.pem"
export MARCHAT_TLS_KEY_FILE="./key.pem"
# Start server (will show wss:// in banner)
./marchat-server
Without TLS (development/testing):
# No TLS certificates set
export MARCHAT_ADMIN_KEY="your-secure-key"
export MARCHAT_USERS="admin1,admin2"
# Start server (will show ws:// in banner)
./marchat-server
The client connection URL automatically reflects the server's TLS status:
- TLS enabled: Connect to
wss://host:port/ws
- TLS disabled: Connect to
ws://host:port/ws
The server banner displays the correct WebSocket URL scheme based on TLS configuration.
For development and testing with self-signed certificates, you can bypass TLS verification:
# Connect with TLS verification bypass
./marchat-client --skip-tls-verify --server wss://localhost:8080/ws
# Regular connection (with verification)
./marchat-client --server wss://localhost:8080/ws
Warning
Security Warning: Use --skip-tls-verify
only for development and testing. Production deployments should use valid TLS certificates.
The plugin system allows you to extend marchat's functionality with custom commands and features. Plugins are automatically downloaded from the configured registry.
By default, marchat uses the GitHub plugin registry. You can configure a custom registry:
# Use default GitHub registry
export MARCHAT_PLUGIN_REGISTRY_URL="https://raw.githubusercontent.com/Cod-e-Codes/marchat-plugins/main/registry.json"
# Use custom registry
export MARCHAT_PLUGIN_REGISTRY_URL="https://my-registry.com/plugins.json"
Command | Description | Example |
---|---|---|
:store |
Browse available plugins | :store |
:plugin install <name> |
Install a plugin | :plugin install echo |
:plugin uninstall <name> |
Remove a plugin | :plugin uninstall echo |
:plugin list |
List installed plugins | :plugin list |
- Echo: Simple echo plugin for testing
The ban history gaps feature prevents banned users from seeing messages that were sent during their ban periods. This creates a more effective moderation experience by ensuring users cannot access conversation history from when they were excluded from the chat.
When enabled, the system:
- Tracks ban events in a dedicated
ban_history
table - Records ban/unban timestamps with admin attribution
- Filters message history for users with ban records
- Maintains performance by only filtering for users who have been banned
Set the environment variable to enable this feature:
# Enable ban history gaps (enabled by default)
export MARCHAT_BAN_HISTORY_GAPS=true
# Start server with feature enabled
./marchat-server
With Ban History Gaps Enabled:
- User gets banned → cannot see new messages
- User gets unbanned → reconnects and sees only messages sent after their unban
- Messages sent during ban period are permanently hidden from that user
With Ban History Gaps Disabled:
- User gets banned → cannot see new messages
- User gets unbanned → reconnects and sees all messages (including those sent during ban)
Shortcut | Description |
---|---|
Ctrl+H |
Toggle help overlay with all commands and shortcuts |
Enter |
Send message |
Esc |
Quit application |
↑/↓ |
Scroll through chat history |
PgUp/PgDn |
Page through chat history |
Ctrl+C/V/X |
Copy/Paste/Cut text |
Ctrl+A |
Select all text |
Tip: Press Ctrl+H
to see the complete help overlay with all available commands!
marchat supports multiple visual themes to customize your chat experience:
Theme | Description | Best For |
---|---|---|
system (default) | Minimal styling that respects your terminal's color scheme | Users who prefer their terminal theme, accessibility, high contrast |
patriot | Red, white, and blue color scheme | American patriotic theme |
retro | Orange and green retro terminal colors | Classic terminal/hacker aesthetic |
modern | Blue and gray modern design | Clean, professional appearance |
Changing Themes:
- During setup: Interactive configuration will prompt for theme selection
- Runtime: Use
:theme <name>
command (e.g.,:theme system
) - Config file: Set
"theme": "system"
in yourconfig.json
- Command line: Use
--theme system
flag
The system theme is the default because it respects your terminal's existing color configuration, ensuring accessibility and preventing color conflicts.
marchat includes audio notification support to alert you when new messages arrive:
Setting | Description | Default |
---|---|---|
Bell Enabled | Play audio alert for all new messages | false |
Bell on Mention Only | Only play bell when mentioned with @username |
false |
Bell Commands:
:bell
- Toggle bell notifications on/off:bell-mention
- Toggle bell only on mentions mode
How it works:
- Uses the ASCII bell character (
\a
) which works on most terminal emulators - Includes rate limiting (500ms minimum between bells) to prevent spam
- Respects your terminal's volume settings
- Automatically saves your preferences to the config file
Configuration:
- Runtime: Use
:bell
and:bell-mention
commands - Config file: Set
"enable_bell": true
and"bell_on_mention": false
in yourconfig.json
Command | Description | Example |
---|---|---|
:theme <name> |
Switch theme | :theme system |
:time |
Toggle 12/24-hour format | :time |
:clear |
Clear chat buffer | :clear |
:sendfile [path] |
Send file (configurable; default 1MB). Use without path for file picker | :sendfile document.txt or :sendfile |
:savefile <name> |
Save received file | :savefile received.txt |
:code |
Open code snippet composer | :code |
:bell |
Toggle message bell notifications | :bell |
:bell-mention |
Toggle bell only on mentions | :bell-mention |
:admin |
Open admin panel (admin only) | :admin |
marchat supports file sharing with two methods:
Direct File Send:
:sendfile /path/to/file.txt
Interactive File Picker:
:sendfile
This opens a file browser where you can:
- Navigate directories with arrow keys
- Enter directories by pressing Enter on folder items
- Go up one level using the ".. (Parent Directory)" option
- View file sizes and types
- Filter by allowed file types (text, code, images, documents, archives)
- Send files up to the configured maximum (default 1MB)
Supported File Types:
- Text:
.txt
,.md
,.json
,.yaml
,.xml
,.csv
,.log
,.conf
- Code:
.go
,.py
,.js
,.ts
,.java
,.c
,.cpp
,.h
,.html
,.css
- Images:
.png
,.jpg
,.jpeg
,.gif
,.bmp
,.svg
- Documents:
.pdf
,.doc
,.docx
,.xls
,.xlsx
,.ppt
,.pptx
- Archives:
.zip
,.tar
,.gz
,.rar
Command | Description | Admin Only |
---|---|---|
:store |
Open plugin store | No |
:plugin list |
List installed plugins | No |
:plugin install <name> |
Install plugin | Yes |
:plugin uninstall <name> |
Uninstall plugin | Yes |
Command | Description | Example |
---|---|---|
:cleardb |
Wipe server database | :cleardb |
:kick <username> |
Kick user (24h temporary ban) | :kick user1 |
:ban <username> |
Ban user (permanent until unban) | :ban user1 |
:unban <username> |
Remove permanent ban | :unban user1 |
:allow <username> |
Override kick early (allow back) | :allow user1 or Ctrl+Shift+A |
:cleanup |
Clean up stale connections | :cleanup |
:forcedisconnect <username> |
Force disconnect user (for stale connections) | :forcedisconnect user1 |
Connect as admin:
./marchat-client --username admin1 --admin --admin-key your-key --server ws://localhost:8080/ws
Note: When E2E encryption is enabled, admin commands typed in chat (like :allow username
) will be encrypted and won't work. Use the hotkey alternatives instead (e.g., Ctrl+Shift+A
for allow command).
marchat uses a two-tier moderation system designed for flexibility and clarity:
Temporary Kicks (24 hours):
- Use
:kick <username>
for temporary discipline - User is automatically allowed back after 24 hours
- Can be overridden early with
:allow <username>
- Ideal for cooling-off periods or minor infractions
Permanent Bans (indefinite):
- Use
:ban <username>
for serious violations - User remains banned until manually unbanned
- Only removed with
:unban <username>
- Ideal for persistent troublemakers or severe violations
Override Commands:
:allow <username>
- Let kicked users back early:unban <username>
- Remove permanent bans- Both commands restore clean message history for the user
marchat offers multiple ways to configure and connect to servers, from interactive setup for new users to quick-start options for returning users.
When you run the client without sufficient flags, it enters interactive configuration mode:
./marchat-client
The interactive mode guides you through:
- Server URL selection
- Username setup
- Admin privileges configuration
- End-to-end encryption setup
- Theme selection
- Profile saving for future use
For returning users, marchat provides convenient quick-start options:
# Auto-connect to most recently used profile
./marchat-client --auto
# Select from saved connection profiles
./marchat-client --quick-start
The client automatically saves connection profiles in platform-appropriate locations:
- Windows:
%APPDATA%\marchat\profiles.json
- macOS:
~/Library/Application Support/marchat/profiles.json
- Linux:
~/.config/marchat/profiles.json
Profiles store non-sensitive connection settings like server URL, username, and preferences. Sensitive data (admin keys, keystore passphrases) are prompted for each session.
For automation and scripts, you can still use traditional command-line flags:
# Basic connection
./marchat-client --server ws://localhost:8080/ws --username alice
# Admin connection
./marchat-client --server ws://localhost:8080/ws --username admin --admin --admin-key your-key
# E2E encrypted connection
./marchat-client --server ws://localhost:8080/ws --username alice --e2e --keystore-passphrase your-passphrase
# Non-interactive mode (requires all necessary flags)
./marchat-client --non-interactive --server ws://localhost:8080/ws --username alice
marchat uses global E2E encryption for secure group chat. Individual user-to-user encryption has been simplified in favor of a shared global encryption model that's easier to use and manage.
Enable E2E encryption:
./marchat-client --e2e --keystore-passphrase your-passphrase --username alice --server ws://localhost:8080/ws
marchat supports global E2E encryption for public channels, allowing secure group chat. This feature uses a shared global encryption key that all clients can use to encrypt and decrypt messages in public channels.
- Shared Key: All clients use the same global encryption key for public channels
- Simple Setup: Shared key model eliminates complex key management
- Environment Variable: Set
MARCHAT_GLOBAL_E2E_KEY
to share the same key across clients - Automatic Generation: If no global key is provided, a new one is generated and displayed
Option 1: Use Environment Variable (Recommended for shared deployments)
# Generate a 32-byte key and encode as base64
openssl rand -base64 32
# Set the environment variable with the generated key
export MARCHAT_GLOBAL_E2E_KEY="your-generated-base64-key"
# Run client with E2E enabled
./marchat-client --e2e --keystore-passphrase your-passphrase --username alice --server ws://localhost:8080/ws
Option 2: Let marchat Generate a Key
# Run client without environment variable - marchat will generate a new key
./marchat-client --e2e --keystore-passphrase your-passphrase --username alice --server ws://localhost:8080/ws
# The client will display the generated key:
# 🔐 Generated new global E2E key (ID: RsLi9ON0ZYvEPOmyMs1IhWL5vPTGEfamExCPuaESV7M=)
# 💡 Set MARCHAT_GLOBAL_E2E_KEY=fF+HkmGArkPNsdb+M+qj/JgBmCTV8R0J7zEW80Izjtw= to share this key across clients
To enable multiple clients to communicate securely, share the global key:
- Copy the generated key from the client output
- Set the environment variable on all client machines:
export MARCHAT_GLOBAL_E2E_KEY="fF+HkmGArkPNsdb+M+qj/JgBmCTV8R0J7zEW80Izjtw="
- Run all clients with the same global key
When global E2E is working correctly, you'll see:
🔐 Using global E2E key from environment variable
🌐 Global chat encryption: ENABLED (Key ID: RsLi9ON0ZYvEPOmyMs1IhWL5vPTGEfamExCPuaESV7M=)
✅ Encryption validation passed
🔐 E2E encryption enabled with keystore: config/keystore.dat
Warning
Change default admin key immediately
The default admin key changeme
is insecure. Generate a secure key:
openssl rand -hex 32
-
Generate Secure Keys:
# Admin key openssl rand -hex 32 # JWT secret (optional) openssl rand -base64 32
-
Secure File Permissions:
# Secure database file chmod 600 ./config/marchat.db # Secure config directory chmod 700 ./config
-
Production Deployment:
- Use
wss://
for secure WebSocket connections - Implement reverse proxy (nginx/traefik)
- Restrict server access to trusted networks
- Use Docker secrets for sensitive environment variables
- Use
When enabled, E2E encryption provides:
- Forward Secrecy: Unique session keys per conversation
- Server Privacy: Server cannot read encrypted messages
- Key Management: Local encrypted keystore with passphrase protection
- Global Encryption: Shared global key for public channel encryption
Issue | Solution |
---|---|
Connection failed | Verify server URL uses ws:// or wss:// |
TLS certificate errors | Ensure certificate and key files are readable and valid |
Admin commands not working | Ensure --admin flag and correct --admin-key |
Clipboard not working (Linux) | Install xclip : sudo apt install xclip |
Port already in use | Change port: export MARCHAT_PORT=8081 |
Database migration fails | Ensure proper database file permissions and backup before building from source |
Message history missing after update | Expected behavior - user message states reset for improved ban/unban experience |
Server fails to start after source build | Check database permissions - migrations are automatic |
Ban history gaps not working | Ensure MARCHAT_BAN_HISTORY_GAPS=true is set (default) and database has ban_history table |
TLS certificate errors | Use --skip-tls-verify flag for development with self-signed certificates |
Plugin installation fails | Check MARCHAT_PLUGIN_REGISTRY_URL is accessible and registry format is valid |
E2E encryption not working | Ensure --e2e flag is used and keystore passphrase is provided. Check debug logs for detailed error messages |
Global E2E key not working | Verify MARCHAT_GLOBAL_E2E_KEY is set correctly and is a valid base64-encoded 32-byte key. Use openssl rand -base64 32 to generate a valid key |
"no session key found for global" error | Fixed in latest version - global E2E key support automatically handles this error |
Blank encrypted messages | Fixed in v0.3.0-beta.5 - ensure you're using the latest version and have added recipient public keys with :addkey |
E2E startup failures | Fixed in v0.3.0-beta.6 - "conversation: test" session key issue resolved |
Username already taken | If you disconnected ungracefully (Ctrl+C), use admin :forcedisconnect <username> to remove stale connection |
Stale connections preventing login | Server automatically cleans up dead connections every 5 minutes, or use admin :cleanup command |
Client frozen during startup | Fixed in latest version - --quick-start flag now uses proper UI instead of console input |
marchat includes robust stale connection cleanup to prevent "username already taken" errors when clients disconnect ungracefully.
Automatic Cleanup:
- Server automatically detects and removes stale connections every 5 minutes
- Uses WebSocket ping messages to identify broken connections
- No manual intervention required for most cases
Manual Cleanup (Admin Commands):
# Clean up all stale connections immediately
:cleanup
# Force disconnect a specific user (useful for your own stale connection)
:forcedisconnect username
# Example: Remove your own stale connection after ungraceful disconnect
:forcedisconnect myusername
Common Scenarios:
- Client crashes or Ctrl+C: Server detects within 5 minutes and cleans up automatically
- Network interruption: Stale connection removed on next cleanup cycle
- Immediate reconnection needed: Admin can use
:forcedisconnect
for instant cleanup - Multiple stale connections: Use
:cleanup
to remove all dead connections at once
Local Network:
# Ensure server binds to all interfaces
export MARCHAT_PORT=8080
./marchat-server
See the project roadmap for planned features, performance enhancements, and future development goals.
- GitHub Issues: Report bugs
- GitHub Discussions: Ask questions
- Documentation: Plugin Ecosystem
- Security: Security Policy
marchat includes a foundational test suite covering core functionality, cryptographic operations, and the plugin system. The test suite provides good coverage for smaller utility packages but limited coverage for the main application components.
# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run tests for specific package
go test ./server -v
# Run tests with timeout (recommended for CI)
go test ./... -timeout 10s
Package | Coverage | Status | Notes |
---|---|---|---|
shared |
79.4% | High | Small utility package (~235 LOC) |
config |
78.3% | High | Small utility package (~523 LOC) |
plugin/store |
47.1% | Medium | Medium-sized package (~494 LOC) |
plugin/host |
22.3% | Low | Medium-sized package (~412 LOC) |
plugin/manager |
12.4% | Low | Medium-sized package (~383 LOC) |
server |
11.9% | Low | Large package (~4300 LOC) |
client |
0% | None | Large package (~4500 LOC) |
plugin/license |
0% | None | Small package (~188 LOC) |
Overall estimated coverage: ~15% (weighted by lines of code)
- Linux/macOS:
./test.sh
- Windows:
.\test.ps1
For detailed testing information, see TESTING.md.
We welcome contributions! See the contribution guidelines for:
- Development setup
- Code style guidelines
- Pull request process
Quick Start for Contributors:
git clone https://github.com/Cod-e-Codes/marchat.git
cd marchat
go mod tidy
go test ./...
Special thanks to these wonderful communities and bloggers for featuring and supporting marchat:
- Self-Host Weekly by Ethan Sholly
- mtkblogs.com by Reggie
- Terminal Trove for including marchat in their curated terminal tools list
For a full list of contributors, see CONTRIBUTORS.md.
License: MIT License
Commercial Support: Contact [email protected]