Skip to content

Lightweight terminal chat with server/client binaries, real-time WebSocket messaging, optional end-to-end encryption, plugins, file sharing, admin panel, and code snippets. Built in Go with Bubble Tea and SQLite; ideal for developers and small teams.

License

Notifications You must be signed in to change notification settings

Cod-e-Codes/marchat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

marchat

marchat - terminal chat application

Go CI MIT License Go Version GitHub all releases Docker Pulls GitHub tag (latest SemVer)

A lightweight terminal chat with real-time messaging over WebSockets, optional E2E encryption, and a flexible plugin ecosystem. Built for developers who prefer the command line.

Latest Updates

v0.8.0-beta.7 (Current)

  • Real-time log capture: Admin panels now display live server logs from memory buffer
  • OS-specific log export: Logs export to appropriate directories (Windows/macOS/Linux/Android)
  • Metrics tracking: Connection and disconnect counters now display accurate totals
  • Structured logging: Converted hub and server events to use structured loggers
  • Live updates: Admin panel logs grow in real-time as events occur

Recent Releases

  • v0.8.0-beta.6: Profile selection bug fix, object-based returns
  • v0.8.0-beta.5: Database backup fix, improved admin commands
  • v0.8.0-beta.4: Interactive server setup, simplified configuration
  • v0.8.0-beta.3: Environment variables only setup, container-friendly configuration
  • v0.8.0-beta.2: Interactive server configuration, profile management
  • v0.8.0-beta.1: Comprehensive test suite, cross-platform testing
  • v0.7.0-beta.7: Advanced security hardening, session management

Full changelog on GitHub releases.

Server Demo Client Demo

Features

  • Terminal UI - Beautiful TUI built with Bubble Tea
  • Real-time Chat - Fast WebSocket messaging with SQLite backend (PostgreSQL/MySQL planned)
  • Plugin System - Remote registry with :store and :plugin commands
  • E2E Encryption - X25519/ChaCha20-Poly1305 with global encryption
  • File Sharing - Send files up to 1MB (configurable) with interactive picker
  • Admin Controls - User management, bans, kick system with ban history gaps
  • Bell Notifications - Audio alerts with :bell and :bell-mention
  • Themes - System (default), patriot, retro, modern
  • Docker Support - Containerized deployment with security features
  • Health Monitoring - /health and /health/simple endpoints with system metrics
  • Structured Logging - JSON logs with component separation and user tracking
  • Cross-Platform - Runs on Linux, macOS, Windows, and Android/Termux

Overview

marchat started as a fun weekend project for father-son coding sessions and has evolved into a lightweight, self-hosted terminal chat application designed specifically for developers who love the command line. Currently runs with SQLite, with PostgreSQL and MySQL support planned for greater scalability.

Key Benefits:

  • Self-hosted: No external services required
  • Cross-platform: Linux, macOS, Windows, and Android/Termux
  • Secure: Optional E2E encryption with X25519/ChaCha20-Poly1305
  • Extensible: Plugin ecosystem for custom functionality
  • Lightweight: Minimal resource usage, perfect for servers
Cross-Platform Theme Switching

Quick Start

1. Generate Admin Key

openssl rand -hex 32

2. Start Server

Option A: Environment Variables (Recommended)

export MARCHAT_ADMIN_KEY="your-generated-key"
export MARCHAT_USERS="admin1,admin2"
./marchat-server

# With admin panel
./marchat-server --admin-panel

# With web panel
./marchat-server --web-panel

Option B: Interactive Setup

./marchat-server --interactive

3. Connect Client

# Admin connection
./marchat-client --username admin1 --admin --admin-key your-key --server ws://localhost:8080/ws

# Regular user
./marchat-client --username user1 --server ws://localhost:8080/ws

# Or use interactive mode
./marchat-client

Database Schema

Key tables for message tracking and moderation:

  • messages: Core message storage with message_id
  • user_message_state: Per-user message history state
  • ban_history: Ban/unban event tracking for history gaps

Installation

Binary Installation:

# Linux (amd64)
wget https://github.com/Cod-e-Codes/marchat/releases/download/v0.8.0-beta.3/marchat-v0.8.0-beta.3-linux-amd64.zip
unzip marchat-v0.8.0-beta.3-linux-amd64.zip && chmod +x marchat-*

# macOS (amd64)
wget https://github.com/Cod-e-Codes/marchat/releases/download/v0.8.0-beta.3/marchat-v0.8.0-beta.3-darwin-amd64.zip
unzip marchat-v0.8.0-beta.3-darwin-amd64.zip && chmod +x marchat-*

# Windows - PowerShell
iwr -useb https://raw.githubusercontent.com/Cod-e-Codes/marchat/main/install.ps1 | iex

Docker:

docker pull codecodesxyz/marchat:v0.8.0-beta.2
docker run -d -p 8080:8080 \
  -e MARCHAT_ADMIN_KEY=$(openssl rand -hex 32) \
  -e MARCHAT_USERS=admin1,admin2 \
  codecodesxyz/marchat:v0.8.0-beta.2

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

Prerequisites for source build:

  • Go 1.23+ (download)
  • Linux clipboard support: sudo apt install xclip (Ubuntu/Debian) or sudo yum install xclip (RHEL/CentOS)

Configuration

Essential Environment Variables

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_TLS_CERT_FILE No - TLS certificate (enables wss://)
MARCHAT_TLS_KEY_FILE No - TLS private key
MARCHAT_GLOBAL_E2E_KEY No - Base64 32-byte global encryption key
MARCHAT_MAX_FILE_BYTES No 1048576 Max file size (1MB default)

Additional variables: MARCHAT_LOG_LEVEL, MARCHAT_CONFIG_DIR, MARCHAT_BAN_HISTORY_GAPS, MARCHAT_PLUGIN_REGISTRY_URL, MARCHAT_MAX_FILE_MB

Interactive Setup: Use --interactive flag for guided server configuration when environment variables are missing.

Admin Commands

User Management

Command Description Hotkey
:ban <user> Permanent ban Ctrl+B (with user selected)
:kick <user> 24h temporary ban Ctrl+K (with user selected)
:unban <user> Remove permanent ban Ctrl+Shift+B
:allow <user> Override kick early Ctrl+Shift+A
:forcedisconnect <user> Force disconnect user Ctrl+F (with user selected)
:cleanup Clean stale connections -

Database Operations (:cleardb or Ctrl+D menu)

  • Clear DB - Wipe all messages
  • Backup DB - Create database backup
  • Show Stats - Display database statistics

User Commands

Command Description
:theme <name> Switch theme (system/patriot/retro/modern)
:time Toggle 12/24-hour format
:clear Clear chat buffer
:sendfile [path] Send file (or open picker without path)
:savefile <name> Save received file
:code Open code composer with syntax highlighting
:bell Toggle message notifications
:bell-mention Toggle mention-only notifications
:store Browse plugin store
:plugin install/list/uninstall Manage plugins

File Sharing

Direct send:

:sendfile /path/to/file.txt

Interactive picker:

:sendfile

Navigate with arrow keys, Enter to select/open folders, ".. (Parent Directory)" to go up.

Supported types: Text, code, images, documents, archives (.txt, .md, .json, .go, .py, .js, .png, .jpg, .pdf, .zip, etc.)

Keyboard Shortcuts

General

Key Action
Ctrl+H Toggle help overlay
Enter Send message
Esc Quit
↑/↓ Scroll history
PgUp/PgDn Page through history
Ctrl+C/V/X/A Copy/Paste/Cut/Select all

Admin Interface (Client)

Key Action
Ctrl+U Select/cycle user
Ctrl+D Database operations menu
Ctrl+K Kick selected user
Ctrl+B Ban selected user
Ctrl+F Force disconnect selected user
Ctrl+Shift+B Unban user (prompts for username)
Ctrl+Shift+A Allow user (prompts for username)

Server

Key Action
Ctrl+A Open terminal admin panel

Admin Panels

Terminal Admin Panel

Enable with --admin-panel flag, then press Ctrl+A to access:

  • Real-time server statistics (users, messages, performance)
  • User management interface
  • Plugin configuration
  • Database operations
  • Requires terminal environment (auto-disabled in systemd/non-terminal)

Web Admin Panel

Enable with --web-panel flag, access at http://localhost:8080/admin:

  • Secure session-based login (1-hour expiration)
  • Live dashboard with metrics visualization
  • RESTful API endpoints with X-Admin-Key auth
  • CSRF protection on all state-changing operations
  • HttpOnly cookies with SameSite protection

API Example:

curl -H "Cookie: admin_session=YOUR_SESSION" http://localhost:8080/admin/api/overview

TLS Support

When to Use TLS

  • Public deployments: Server accessible from internet
  • Production environments: Enhanced security required
  • Corporate networks: Security policy compliance
  • HTTPS reverse proxies: Behind nginx, traefik, etc.

Configuration Examples

With TLS (production):

# Generate self-signed cert (testing only)
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

export MARCHAT_ADMIN_KEY="your-key"
export MARCHAT_USERS="admin1,admin2"
export MARCHAT_TLS_CERT_FILE="./cert.pem"
export MARCHAT_TLS_KEY_FILE="./key.pem"
./marchat-server  # Shows wss:// in banner

Without TLS (development):

export MARCHAT_ADMIN_KEY="your-key"
export MARCHAT_USERS="admin1,admin2"
./marchat-server  # Shows ws:// in banner

Client with TLS:

# With verification (production)
./marchat-client --server wss://localhost:8080/ws

# Skip verification (dev/self-signed only)
./marchat-client --skip-tls-verify --server wss://localhost:8080/ws

Warning: Use --skip-tls-verify only for development. Production should use valid CA-signed certificates.

E2E Encryption

Global encryption for secure group chat using shared keys across all clients.

How It Works

  • Shared Key Model: All clients use same global encryption key for public channels
  • Simplified Management: No complex per-user key exchange
  • X25519/ChaCha20-Poly1305: Industry-standard encryption algorithms
  • Environment Variable: MARCHAT_GLOBAL_E2E_KEY for key distribution
  • Auto-Generation: Creates new key if none provided

Setup Options

Option 1: Shared Key (Recommended)

# Generate 32-byte key
openssl rand -base64 32

# Set on all clients
export MARCHAT_GLOBAL_E2E_KEY="your-generated-key"

# Connect with E2E
./marchat-client --e2e --keystore-passphrase your-pass --username alice --server ws://localhost:8080/ws

Option 2: Auto-Generate

# Client generates and displays new key
./marchat-client --e2e --keystore-passphrase your-pass --username alice --server ws://localhost:8080/ws

# Output shows:
# 🔐 Generated new global E2E key (ID: RsLi9ON0...)
# 💡 Set MARCHAT_GLOBAL_E2E_KEY=fF+HkmGArkPNsdb+... to share this key

Expected Output

🔐 Using global E2E key from environment variable
🌐 Global chat encryption: ENABLED (Key ID: RsLi9ON0...)
✅ Encryption validation passed
🔐 E2E encryption enabled with keystore: config/keystore.dat

Security Features

  • Forward Secrecy: Unique session keys per conversation
  • Server Privacy: Server cannot read encrypted messages
  • Local Keystore: Encrypted with passphrase protection
  • Validation: Automatic encryption/decryption testing on startup

Plugin System

Extend functionality with remote plugins from configured registry.

Configuration

# Default GitHub registry
export MARCHAT_PLUGIN_REGISTRY_URL="https://raw.githubusercontent.com/Cod-e-Codes/marchat-plugins/main/registry.json"

# Custom registry
export MARCHAT_PLUGIN_REGISTRY_URL="https://my-registry.com/plugins.json"

Commands

:store                    # Browse available plugins
:plugin install echo      # Install plugin
:plugin list              # List installed
:plugin uninstall echo    # Remove plugin

Available Plugins

  • Echo: Simple echo plugin for testing

See PLUGIN_ECOSYSTEM.md for development guide.

Moderation System

Temporary Kicks (24 hours):

  • :kick <username> or Ctrl+K for temporary discipline
  • Auto-allowed after 24 hours, or override early with :allow
  • Ideal for cooling-off periods

Permanent Bans (indefinite):

  • :ban <username> or Ctrl+B for serious violations
  • Remains until manual :unban or Ctrl+Shift+B
  • Ideal for persistent troublemakers

Ban History Gaps: Prevents banned users from seeing messages sent during ban periods. Enable with MARCHAT_BAN_HISTORY_GAPS=true (default).

Client Configuration

Interactive Mode (Default)

./marchat-client

Guides through server URL, username, admin privileges, E2E encryption, theme selection, and profile saving.

Quick Start Options

# Auto-connect to recent profile
./marchat-client --auto

# Select from saved profiles
./marchat-client --quick-start

Profile Management

Profiles stored in platform-appropriate locations:

  • Windows: %APPDATA%\marchat\profiles.json
  • macOS: ~/Library/Application Support/marchat/profiles.json
  • Linux: ~/.config/marchat/profiles.json

During profile selection:

  • i or v - View profile details
  • r - Rename profile
  • d - Delete profile

Traditional 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
./marchat-client --server ws://localhost:8080/ws --username alice --e2e --keystore-passphrase your-pass

# Non-interactive (requires all flags)
./marchat-client --non-interactive --server ws://localhost:8080/ws --username alice

Security Best Practices

  1. Generate Secure Keys

    # Admin key (64 hex characters)
    openssl rand -hex 32
    
    # Global E2E key (base64-encoded 32 bytes)
    openssl rand -base64 32
  2. Secure File Permissions

    chmod 600 ./config/marchat.db    # Database
    chmod 600 ./config/keystore.dat  # Keystore
    chmod 700 ./config               # Config directory
  3. Production Deployment

    • Use TLS (wss://) with valid CA-signed certificates
    • Deploy behind reverse proxy (nginx/traefik)
    • Restrict server access to trusted networks
    • Use Docker secrets for sensitive environment variables
    • Enable rate limiting and brute force protection
    • Monitor security logs regularly
  4. E2E Encryption

    • Store MARCHAT_GLOBAL_E2E_KEY securely
    • Use strong keystore passphrases
    • Never share keystores between users
    • Rotate keys periodically for sensitive deployments

Troubleshooting

Issue Solution
Connection failed Verify ws:// or wss:// protocol in URL
Admin commands not working Check --admin flag and correct --admin-key
Admin commands encrypted Hotkey alternatives work when E2E enabled (e.g., Ctrl+Shift+A)
Clipboard issues (Linux) Install xclip: sudo apt install xclip
Port in use Change port: export MARCHAT_PORT=8081
Database migration fails Check file permissions, backup before source build
Message history missing Expected after updates - user states reset for ban/unban improvements
Ban history gaps not working Ensure MARCHAT_BAN_HISTORY_GAPS=true (default) and ban_history table exists
TLS certificate errors Use --skip-tls-verify for dev with self-signed certs
Plugin installation fails Verify MARCHAT_PLUGIN_REGISTRY_URL is accessible and valid JSON
E2E encryption errors Ensure --e2e flag and keystore passphrase provided, check debug logs
Global E2E key errors Verify key is valid base64-encoded 32-byte key: openssl rand -base64 32
Blank encrypted messages Fixed in v0.3.0-beta.5+ - ensure latest version
Username already taken Use admin :forcedisconnect <user> or wait 5min for auto-cleanup
Stale connections Server auto-cleans every 5min, or admin use :cleanup
Client frozen at startup Fixed in latest - --quick-start uses proper UI

Stale Connection Management

Automatic: Server detects and removes stale connections every 5 minutes using WebSocket ping.

Manual (Admin):

:cleanup                    # Clean all stale connections
:forcedisconnect username   # Force disconnect specific user

Common scenarios:

  • Client crash/Ctrl+C: Auto-cleaned within 5 minutes
  • Network interruption: Removed on next cleanup cycle
  • Immediate reconnect: Admin uses :forcedisconnect

Testing

Foundational test suite covering core functionality, cryptography, and plugins.

Running Tests

go test ./...              # Run all tests
go test -cover ./...       # With coverage
go test ./server -v        # Specific package
go test ./... -timeout 10s # With timeout (CI recommended)

Test Scripts

  • Linux/macOS: ./test.sh
  • Windows: .\test.ps1

Coverage Summary

Package Coverage Size Status
plugin/license 83.1% 229 LOC High
shared 82.4% 283 LOC High
config 78.6% 304 LOC High
client/crypto 76.5% 289 LOC High
client/config 55.2% 1816 LOC Medium
plugin/store 46.8% 559 LOC Medium
cmd/license 42.2% 160 LOC Medium
server 35.4% 5391 LOC Medium
client 27.8% 3679 LOC Medium
plugin/host 22.3% 486 LOC Low
plugin/manager 12.4% 464 LOC Low
cmd/server 5.6% 403 LOC Low

Overall: 37.1% - See TESTING.md for detailed information.

Contributing

We welcome contributions! See CONTRIBUTING.md for:

  • Development setup instructions
  • Code style guidelines and conventions
  • Pull request process and requirements
  • Testing expectations

Quick Start:

git clone https://github.com/Cod-e-Codes/marchat.git
cd marchat
go mod tidy
go test ./...

Documentation

Getting Help

Appreciation

Thanks to Self-Host Weekly, mtkblogs.com, and Terminal Trove for featuring marchat!

See CONTRIBUTORS.md for full contributor list.


License: MIT License

About

Lightweight terminal chat with server/client binaries, real-time WebSocket messaging, optional end-to-end encryption, plugins, file sharing, admin panel, and code snippets. Built in Go with Bubble Tea and SQLite; ideal for developers and small teams.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project