marchat π§
β’β β β β β β β β’⣠⣀⣢⣢⣢⣢⣢⣢⣢⣢⣢⣦β‘β β β β β β β£β£β£β£β£β£β β β β β β β β β β β β
β£Ώβ£·β β β£β£€β£΄β£Ύβ£Ώβ‘Ώβ£Ώβ£§β£Ώβ£Άβ£Ώβ£Ώβ£Ώβ£½β£Ώβ£½β£Ώβ£·β£€β£€β£΄β£Άβ£Ύβ£Ώβ£Ώβ‘Ώβ Ώβ β β Ώβ£·β‘β’β£β£β£β£β‘β β β β
β β£Ώβ£Άβ£Ώβ£Ώβ£β£Ώβ£Άβ£Ώβ£Ώβ£Ώβ£Ώβ£β£Ώβ£β£Ώβ£½β£Ώβ£Ήβ£Ώβ£»β£Ώβ‘Ώβ Ώβ β β β β β’β£β£β£β£β£β£Ώβ Ώβ Ώβ β »β Ώβ’Ώβ‘β β β
β β’Ήβ£Ώβ£Ώβ£Ώβ£Ώβ‘β£Ώβ£―β£Ώβ£Ώβ£Ώβ£Ώβ’Ώβ£Ώβ’»β£β£»β‘β’Ώβ Ώβ£Ώβ£β£β£ ⣀⣴⣢⣾⣿⑿⠿⠿⠻⠿β β β£β£β£β£β£Έβ‘β β β
β β β’»β£Ώβ£Ώβ£Ώβ£Ώβ‘Ώβ£Ώβ‘β£Ώβ£₯β£Ώβ£Ώβ£Ώβ£Ώβ’Ώβ‘Ώβ£Ώβ£Ώβ£·β£Ώβ£Ώβ’Ώβ£Ώβ Ώβ β β β β’β£β£β£β£β‘β£Ώβ£Ώβ Ώβ Ώβ Ώβ’Ώβ‘β β β
β β β β£Ώβ‘β’Ώβ£Ώβ£·β£Ύβ£Ώβ‘β’Ώβ£β£Ώβ£΄β£Ώβ£Ύβ£·β£Ώβ£·β£Ύβ£Ύβ£Ώβ‘β β£β£€β£€β£Άβ£Ύβ£Ώβ Ώβ β β »β Ώβ£β£β£ β£€β£€β£Όβ‘β β β
β β β β Έβ£Ώβ‘β’»β£Ώβ£―β£Έβ£·β£Ύβ‘Ώβ β β β β β β β β β β β£Ώβ£Ώβ Ώβ β β β’β£ β£€β£€β£€β£₯β£½β‘Ώβ Ώβ Ώβ Ώβ Ώβ‘β β β
β β β β β’»β£·β β’»β£Ώβ β β β β’⣠⣀⣴⣢⣢⣢⣢⣾⣢⣾β‘β£β£β£€β£΄β£Ύβ£Ώβ Ώβ β β β β’³β£€β£€β£€β£€β£€β£·β β β
β β β β β β£Ώβ£β β£Ώβ£β£ ⣴⣾⣿⑿β β β β β β β β β β£Ώβ Ώβ β β β β’β£€β£Άβ£Άβ£Άβ£Άβ£Ύβ β β β β β’Ώβ β β
β β β β β β β£Ώβ‘β Έβ£Ώβ‘Ώβ β β β’β£β£€β£΄β£Άβ£Άβ£Άβ£Άβ£Άβ£Ύβ£β£β£€β£€β£Άβ£Ύβ‘Ώβ β β β β β ⣀⣴⣢⣢⠢Ⓙβ£β β
β β β β β β β’Ήβ£Ώβ‘β£Ώβ‘β£β£€β£Ύβ‘Ώβ β β β β β β β β β‘Ώβ β β β β β£β£΄β£Ύβ£Ώβ£Ώβ£Ώβ£Ώβ‘β β β β£β£β£Ώβ‘β
β β β β β β β β’Ώβ£§β’Έβ£Ώβ β β β£β£ ⣀⣴⣢⣾⣿⣿⣿⣿⣧⣀⣀⣢⠾β β β β’β£β£β£β£β’°β£Άβ£Ώβ Ώβ Ώβ Ώβ Ώβ£§β
β β β β β β β β β£Ώβ‘⣿⣠⣴⣿⣿⣿⠿β β β β β β β’ β‘β β β£β£ ⣴⣾⠿⠿β β β β β£Ώβ β β β£β£β£β£Ώβ‘
β β β β β β β β β Έβ£Ώβ£Ώβ‘Ώβ β β β β β β β β β β β Έβ£§β£Άβ Ώβ β β β β β β β β β ⣿⣴⣾⠿β β β β β
β β β β β β β β β β’»β£Ώβ β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β
β β β β β β β β β β β£Ώβ£β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β
β β β β β β β β β β β Έβ£Ώβ‘β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β
β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β
ββββ ββββ βββ βββ
βββββ βββββ βββ βββ
ββββββ ββββββ βββββββ ββββββββ ββββββββ βββββββββ βββββββ βββββββββ
βββ βββββ βββ βββ ββββ βββ βββ βββ βββ βββ βββ
βββ βββ βββ ββββββββ βββ βββ βββ βββ ββββββββ βββ
βββ βββ βββ βββ βββ βββ βββ βββ βββ βββ βββ βββ
βββ βββ βββββββββ βββ ββββββββ βββ βββ βββββββββ βββββ
- Features
- Quick Start
- Usage
- Project Structure
- Admin Mode
- Security
- Tech Stack
- Troubleshooting
- Contributing
- License
marchat
is a minimalist terminal-based group chat app designed for real-time, distraction-free conversations. Whether you're pair programming, self-hosting a LAN party, or just chatting from two terminals, it's lightweight, hackable, and built for fun.
Built for father-son coding sessions, marchat is about sharing the joy of hacking, learning, and chatting in a terminal. It's a fun, retro-inspired project for anyone who loves the command line, real-time collaboration, or just wants a simple, self-hosted chat.
- Terminal UI (TUI): Beautiful, scrollable chat using Bubble Tea
- Real-time WebSocket Chat: Fast, robust, and cross-platform server/client
- Themes: Choose from
patriot
,retro
, ormodern
for a unique look - Emoji Support: Auto-converts common ASCII emoji (e.g.
:)
,:(
,:D
,<3
,:P
) to Unicode - Live User List: See whoβs online in a fixed-width, styled panel (up to 20 users shown)
- @Mention Highlighting: Messages with
@username
highlight for all users in the chat - Admin Mode: Privileged commands (like
:cleardb
) for authenticated admins only - Message Cap:
- Only the last 100 messages are kept in memory for client performance
- The server database automatically caps messages at 1000; oldest messages are deleted to make room for new ones
- Configurable: Set username, server URL, and theme via config file or flags
- Graceful Shutdown: Clean exit and robust connection handling (ping/pong heartbeat)
- ASCII Art Banner: Server displays a beautiful banner with connection info on startup
- Install Go 1.24+ if you havenβt already
- (Check with
go version
in your terminal)
- (Check with
- (Optional, for remote access) Download cloudflared (
cloudflared.exe
on Windows)
π οΈ You can configure marchat via flags or a config.json
. Flags override config file values.
git clone https://github.com/Cod-e-Codes/marchat.git
cd marchat
go mod tidy
go build ./...
go run cmd/server/main.go
Optional: Customize admin settings (admin key is the secret used to authorize admin commands):
go run cmd/server/main.go --admin-username YourName --admin-key your-admin-key
Create config.json
in the project root:
{
"username": "Cody",
"server_url": "ws://localhost:9090/ws",
"theme": "patriot",
"twenty_four_hour": true
}
If you don't have a config file, simply create a new config.json
in your project root using the example above. The client will look for this file by default. You can also specify a different path with the --config
flag.
# With flags:
go run client/main.go --username Cody --theme patriot --server ws://localhost:9090/ws
# Or with config file (loaded from current working directory):
go run client/main.go --config config.json
If no flags or config are provided, the client uses default values.
If you want to make your marchat server accessible from outside your local network (for example, to chat with friends remotely), you can use Cloudflare Tunnel with cloudflared
.
cloudflared tunnel --url http://localhost:9090
This will give you a public https://
URL you can use for your client/server.
- After running the tunnel, Cloudflare will give you a public
https://your-tunnel.trycloudflare.com
URL. - To use it in your client, convert it to a WebSocket URL by replacing
https://
withwss://
and appending/ws
.
Example: If Cloudflare gives you:
https://bold-forest-cat.trycloudflare.com
You should use:
wss://bold-forest-cat.trycloudflare.com/ws
in your client command like this:
go run client/main.go --username Cody --admin --admin-key your-admin-key --server wss://bold-forest-cat.trycloudflare.com/ws
Note:
- You do not need to sign up for a Cloudflare account for temporary tunnels.
- For persistent tunnels or custom domains, see the Cloudflare Tunnel docs.
- Send messages: Type and press Enter
- Quit: Press
ctrl+c
orEsc
to exit the chat - Themes:
patriot
,retro
,modern
(case-insensitive), or leave blank for default - Emoji support: Common ASCII emoticons (e.g.
:)
,:(
,:D
,<3
,:P
) automatically convert to Unicode.- Supported:
:)
,:(
,:D
,<3
,:P
- Supported:
- Scroll: Use Up/Down arrows or your mouse to scroll chat
- Switch theme: Type
:theme <name>
and press Enter (persists in config) - Toggle timestamp format: Type
:time
and press Enter (persists in config) - ASCII art banner: Displays connection info on server startup; can be disabled via config or flag
- Clear chat (client only): Type
:clear
and press Enter (clears your local buffer only β does not affect others) - Clear all messages (wipe DB): Type
:cleardb
and press Enter (admin only β wipes entire database for all users) - Banner: Status and error messages appear above chat
- Mentions: Use
@username
to highlight a user (full-message highlight, not partial) - User List: Up to 20 users are shown in a fixed-width panel, with a styled
+N more
indicator if more are online
marchat/
βββ client/ # TUI client (Bubble Tea)
β βββ main.go
β βββ config/
β βββ config.go
βββ cmd/server/ # Server entrypoint
β βββ main.go
βββ server/ # Server logic (DB, handlers, WebSocket)
β βββ db.go
β βββ handlers.go
β βββ client.go
β βββ hub.go
β βββ schema.sql
βββ shared/ # Shared types
β βββ types.go
βββ config.json # Example or user config file (see Quick Start)
βββ go.mod
βββ go.sum
βββ README.md
Modular architecture: client, server logic, and shared types are separated for clarity and maintainability.
Admin commands like
:cleardb
require:
- The
--admin
flag and a valid--admin-key
(case-insensitive username match)- Only users listed as admins on the server (via repeated --admin flags) can authenticate as admin
- All admin actions are performed over WebSocket (no HTTP endpoints)
β‘ Important: Do not use the default admin key (
changeme
) in production. Change it immediately to avoid security risks.
- To launch the server with multiple admins:
go run cmd/server/main.go --admin Cody --admin Crystal --admin-key your-admin-key
- To connect as admin (WebSocket):
go run client/main.go --username Cody --admin --admin-key your-admin-key --server wss://localhost:9090/ws
- Only authenticated admins can use privileged commands like
:cleardb
. - Admin usernames are case-insensitive (e.g.
Cody
,cody
, andCODY
are equivalent). - The admin key is only sent at handshake, not with every command.
- The
/clear
HTTP endpoint and allreal_user
logic have been removed for security and simplicity.
Production deployment checklist:
- Change the default admin key (
changeme
) to a secure value- Use
wss://
(secure WebSocket) URLs in production, notws://
- Ensure firewall rules allow your chosen port (default: 9090)
- Consider using a reverse proxy (nginx, etc.) for additional security
- Go 1.24+
- Bubble Tea (TUI)
- Lipgloss (styling)
- modernc.org/sqlite (pure Go SQLite, no C compiler required)
- Gorilla WebSocket (real-time messaging)
Platform Support: Runs on Linux, macOS, and Windows terminals supporting ANSI escape sequences.
- Panic:
close of closed channel
- Fixed: The client now guards against double-close of internal channels.
- Client fails to connect with
http://
URL- Use a WebSocket URL:
ws://localhost:9090/ws
orwss://...
for remote. - URL schemes: Use
ws://
for local development,wss://
for production (secure WebSocket)
- Use a WebSocket URL:
- Mentions not highlighted
- Use
@username
exactly (word boundary, not substring).
- Use
- User list not updating
- Ensure server and client are both up to date and using compatible protocols.
- Messages not showing or chat not updating
- Check your WebSocket connection and server logs for errors.
- Old messages missing from chat history
- The server database only keeps the most recent 1000 messages. Older messages are automatically deleted.
- Too many users in user list
- Only up to 20 users are shown, with a styled
+N more
indicator if more are online.
- Only up to 20 users are shown, with a styled
- Cross-platform: Runs on Linux, macOS, and Windows terminals
- Firewall/Port: Ensure port 9090 is open for remote connections
- Admin commands
- All admin commands (like
:cleardb
) are now fully functional for authenticated admins.
- All admin commands (like
If reporting a bug, please include your version or commit hash.
See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
- Dependency Updates: marchat uses Dependabot to automatically check for and propose updates to Go module dependencies.
- Continuous Integration: All pushes and pull requests are checked by GitHub Actions for build, test, and linting. Please ensure your PR passes CI before requesting review.
This project is licensed under the MIT License.