encrypted terminal chat with file xfer, shared terminal acess, sandbox vm supporitn docker, multipass and virtualbox. also local ai model integration.
Go to file
leetcrypt 5de493e895 feat(hh): /pw command, RAM-only direnv autostart, robust lets-hack; coven→clergy
- add /pw (alias /password): reveal this room's password locally (never
  broadcast); surfaced in the F1 help overlay and the join hint
- direnv-autostart/: cd-to-launch a single real-user session via direnv;
  password is minted in memory at launch (never written to disk, matching the
  RAM-only model) and scoped to the child process. setup.sh installs direnv,
  hooks bash/zsh, and `direnv allow`s the dir
- lets-hack.sh: boot a FRESH server by default (replacing any live one) with a
  --reuse opt-out; add -h/--help/-help; guard against killing the tmux session
  you're attached to; switch-client into the coven when run inside tmux
- rename coven→clergy across rust/python/scripts; tests/test_coven.py→test_clergy.py
- snapshots in-progress hack-house client work (sandbox, themes, net, ui)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-31 22:29:17 -07:00
.github/workflows Add Django CI workflow for testing 2026-01-15 18:40:26 +02:00
.venv chore: rename project coven → hack-house ⛧ 2026-05-30 13:29:14 -07:00
cmd_chat feat(hh): /pw command, RAM-only direnv autostart, robust lets-hack; coven→clergy 2026-05-31 22:29:17 -07:00
docs feat(coven): SRP/Fernet crypto parity + multi-user coven foundation ⛧ 2026-05-30 11:47:25 -07:00
hh feat(hh): /pw command, RAM-only direnv autostart, robust lets-hack; coven→clergy 2026-05-31 22:29:17 -07:00
lab feat: add host-chat.sh — one-command server setup with friend instructions 2026-05-25 22:40:57 -07:00
tests feat(hh): /pw command, RAM-only direnv autostart, robust lets-hack; coven→clergy 2026-05-31 22:29:17 -07:00
.gitignore feat(coven): SRP/Fernet crypto parity + multi-user coven foundation ⛧ 2026-05-30 11:47:25 -07:00
cmd_chat.py feat: complete client-server architecture refactoring 2026-01-02 14:42:33 +03:00
CONTRIBUTING.md Add CONTRIBUTING.md file 2026-01-17 16:52:33 +09:00
example.gif New README + Demonstartional video 2026-01-02 20:37:11 +03:00
LICENSE Code refactoring 2023-03-08 18:59:38 +03:00
README.MD docs: rewrite README with complete setup, security, and file transfer guide 2026-05-26 10:57:39 -07:00
requirements.txt feat(coven): SRP/Fernet crypto parity + multi-user coven foundation ⛧ 2026-05-30 11:47:25 -07:00
tests.bat feat: add SRP authentication, improve security 2026-01-02 23:09:00 +03:00

CMD-CHAT

end-to-end encrypted terminal chat with file transfer

License: MIT Python 3.10+


Encrypted chat that runs in your terminal. You host the server, you control the room. Close the window — everything's gone. Messages and files are encrypted client-side before the server ever sees them.

Features

  • End-to-end encrypted — messages encrypted with Fernet (AES-128-CBC + HMAC) before leaving your machine
  • TLS by default — auto-generated self-signed certs, or bring your own
  • SRP authentication — password never sent over the network (zero-knowledge proof)
  • Encrypted file transfer/send, /accept, /reject with SHA-256 verification
  • RAM only — nothing written to disk on the server
  • Rate limiting — brute-force protection on auth endpoints
  • No IP leaks — client IPs never broadcast to other users
  • Password hidden — prompted securely via getpass, never visible in ps or shell history

Install

git clone https://github.com/diorwave/cmd-chat.git
cd cmd-chat
pip install -r requirements.txt

Quick Start

Host a chat room:

python3 cmd_chat.py serve 0.0.0.0 3000

You'll be prompted for a room password (hidden input). An admin token and TLS cert path will print to the console.

Connect to a chat room:

python3 cmd_chat.py connect SERVER_IP 3000 yourname --insecure

--insecure is needed for self-signed certs. You'll be prompted for the room password.

Securing Your Connection

Both parties install Tailscale. Traffic goes through an encrypted WireGuard tunnel. No port forwarding, works across NATs.

# Host
python3 cmd_chat.py serve 0.0.0.0 3000

# Friend connects using your Tailscale IP
python3 cmd_chat.py connect 100.x.x.x 3000 theirname --insecure

Find your Tailscale IP: tailscale ip -4

LAN (same network)

Use your local IP. Both devices must be on the same WiFi/network.

python3 cmd_chat.py connect 192.168.1.x 3000 theirname --insecure

Public Internet

Requires port forwarding on your router (TCP port 3000 to your machine). Use --cert and --key with a real certificate for production use.

python3 cmd_chat.py connect PUBLIC_IP 3000 theirname --insecure

Find your public IP: curl ifconfig.me

Sharing the Room Password

The password must be shared outside the chat. Never send it over an unencrypted channel.

  1. In person — tell them verbally
  2. Signal — disappearing message set to 30 seconds
  3. One-time linkonetimesecret.com (self-destructs after one view)
  4. Split it — send half via Telegram, half via SMS

Chat Commands

Command Action
/send <filepath> Propose a file transfer to the room
/accept Accept a pending file offer
/reject Decline a pending file offer
q Disconnect

File Transfer

Files are chunked (64KB), encrypted with the room key, and relayed through the server as opaque ciphertext. The server never sees file names, contents, or metadata.

alice> /send report.pdf
bob>   "alice wants to send report.pdf (1.2 MB) — /accept or /reject"
bob>   /accept
       Receiving: 100% (1.2 MB/1.2 MB)
       File saved: ./downloads/report.pdf — SHA-256 verified
  • Max file size: 50 MB
  • Files saved to ./downloads/ relative to where the client was launched
  • SHA-256 integrity check on every transfer

CLI Reference

Server

python3 cmd_chat.py serve <bind_ip> <port> [options]
Flag Purpose
--password, -p Room password (prompted if omitted)
--cert Path to TLS certificate
--key Path to TLS private key
--no-tls Disable TLS (local dev only)

Client

python3 cmd_chat.py connect <server_ip> <port> <username> [options]
Flag Purpose
--password, -p Room password (prompted if omitted)
--insecure, -k Skip TLS cert verification (self-signed certs)
--no-tls Connect without TLS

Environment Variable

Set CMD_CHAT_PASSWORD to skip the password prompt for both server and client.

Helper Scripts

./lab/host-chat.sh

One-command server setup. Detects your IPs (Tailscale, LAN, public), prints the exact connect command your friend needs, then starts the server.

./lab/host-chat.sh              # TLS on port 4000
./lab/host-chat.sh --port 5000  # custom port
./lab/host-chat.sh --no-tls     # disable TLS

./lab/setup-lab.sh

Spins up a tmux session with the server and two chat clients side-by-side for local testing.

./lab/setup-lab.sh                          # default lab
./lab/setup-lab.sh --no-tls --port 4001     # plain HTTP
./lab/setup-lab.sh --user1 alice --user2 bob
./lab/setup-lab.sh --teardown               # clean up

Attach with tmux attach -t cmd-chat-lab. Switch panes with Ctrl+B then arrow keys.

How It Works

CLIENT                              SERVER                         CLIENT
  │                                   │                               │
  │── POST /srp/init {A} ──────────► │                               │
  │◄── {B, salt, room_salt} ──────── │                               │
  │                                   │                               │
  │  derive room_key = HKDF(password, room_salt)                      │
  │                                   │                               │
  │── POST /srp/verify {M} ────────► │                               │
  │◄── {H_AMK, ws_token} ─────────── │                               │
  │                                   │                               │
  │══ WSS /ws/chat?ws_token ════════► │ ◄══════════════════════════════│
  │                                   │                               │
  │  encrypt(msg, room_key) ────────► │ ──── ciphertext ────────────► │
  │                                   │           decrypt(ciphertext, room_key)
  │                                   │                               │
  │  server stores ONLY ciphertext    │                               │
  │  server CANNOT read messages      │                               │

SRP (Secure Remote Password) — both sides prove they know the password without transmitting it. A network observer learns nothing.

Room Key — derived independently by each client via HKDF(password, room_salt). All clients with the same password get the same key. The server never has the key.

WebSocket Auth — HMAC-SHA256 token issued after SRP verification. Prevents session hijacking.

Admin

The server prints an admin token at startup. Use it to clear message history:

curl -k -X DELETE https://SERVER:3000/clear \
  -H "Authorization: Bearer <admin-token>"

License

MIT