sshhh-lanchat: ephemeral encrypted terminal chat for your LAN
No server, no accounts, nothing on disk. Same room + same passphrase = same conversation, like a walkie-talkie channel. Close the window and it never happened.
$ curl -fsSL https://raw.githubusercontent.com/granthgg/sshhh-lanchat/main/scripts/get.sh | shtip: someone reading over your shoulder? press Ctrl-B. it works on this page too. any key brings you back.
simulation: the only color on this site lives in there, because -color is where the app spends its color too.
$ man lanchat
what it is
name
lanchat, the sshhh-lanchat client: ephemeral encrypted chat for the people on your Wi-Fi. (the “sshhh” is the instruction manual.)
description
Run it, and you’re in the room called lobby with everyone else on the network who ran it too. Add -r team -k coffee123 and only people with that exact room + passphrase can read a word. Everyone else on the wire sees encrypted noise.
It looks like log output on purpose: to a glance over your shoulder you’re reading build logs, and one keystroke makes that literally true. UDP is stateless, so nothing sent before you joined is visible and nothing survives after you quit. There is no history to search, leak, or subpoena.
lanchat [-r room] [-k pass | -ask] [-color] [-stealth]
| -r team | pick a room (default: lobby) |
| -k … / -ask | make it private: same passphrase, same room |
| -color | a stable color per speaker |
| -stealth | prompt looks like a plain shell |
read the full manual → docs · every flag, command, key, and fix.
$ lanchat --help
what it does
Truly ephemeral
No logs, no history, no database. Close the window and the conversation never happened.
saved: nothing
No server, no accounts
Every copy is a peer. Nobody hosts the room, so nothing can go down or hand over records.
peers only
Encrypted on the wire
AES-256-GCM, key derived from room + passphrase. Wireshark sees only noise.
-k <phrase>
The boss key
Ctrl-B swaps the chat for fake build output. Held messages replay when you're back.
Ctrl-B · /boss
Looks like logs
Dim timestamps, right-aligned names. A glance over your shoulder reads “logs”, not “chat”.
by design
Stealth mode
A plain shell $ prompt, flat logger-style lines, and a bell that stays silent.
-stealth
One ~3 MB binary
Go with zero runtime dependencies. The crypto is the standard library.
go build
Terminal-native comfort
Tab completion, input history, bold mentions, a Dock-badging bell with /snooze.
Tab · /snooze
Built for messy Wi-Fi
Every interface + broadcast fallback, dedup, 20 s re-scans, VPN tunnels skipped.
resilient
install
$ curl -fsSL https://raw.githubusercontent.com/granthgg/sshhh-lanchat/main/scripts/get.sh | sh$ irm https://raw.githubusercontent.com/granthgg/sshhh-lanchat/main/scripts/get.ps1 | iexOne paste: it fetches the right binary from the latest release, verifies its SHA-256 checksum, and puts lanchat on your PATH. No Go, no git, no build, and no SmartScreen or Gatekeeper popups.
simulation: checksum verification is the part browser popups never gave you.
then just: lanchat and you’re in the lobby.
private room: lanchat -r team -ask
$ less docs/ARCHITECTURE.md
how it works
There is no host and no server. Every instance sends and receives on a UDP multicast group derived from the room name, and rooms are isolated by encryption, not by address: a wrong passphrase simply fails to decrypt.
┌ magic "TC02" · 4 bytes
├ nonce 12 B · random per message
└ seal AES-256-GCM ciphertext + tag
without the key: just noise┌──────────────┬────────────────┬───────────────────────────────┐ │ magic "TC02" │ nonce (12 B) │ AES-256-GCM ciphertext + tag │ │ 4 bytes │ random per-msg │ without the key: just noise │ └──────────────┴────────────────┴───────────────────────────────┘
- nothing to keep running: join or leave any time; the room can’t go down
- truly ephemeral: you only receive while you’re listening
- tiny footprint: idle CPU ~0; TTL 1 keeps traffic on the segment
- privacy on the wire: without the passphrase, ciphertext is all there is
| machine on Ethernet and Wi-Fi | multicast is sent on every usable interface |
| office Wi-Fi filters multicast | a directed-broadcast copy per subnet, deduped |
| AP roam · sleep-wake · new DHCP | interfaces re-scanned every 20 s, groups re-joined |
| an active VPN owns the route | tunnels are skipped during auto-detection |
| flaky gear drops fragments | frames are capped so they never fragment |
wire format, package layout, threading model: docs/ARCHITECTURE.md
security model: read this
[ what it protects against ]
- shoulder-surfing: the log-like format and the boss key exist for exactly this
- passive sniffing of a private room: captured packets are unreadable without the passphrase
- terminal injection: network text is stripped of control characters
[ what it does not do ]
- open rooms are not private: no passphrase means the key derives from the room name alone; treat it as a public channel on that LAN
- no identity: anyone with the passphrase can use any nickname
- no forward secrecy, no signing: it’s a lightweight LAN toy, not Signal
don’t send anything you’d be unwilling to say out loud in the office. the startup banner always tells you whether the room is OPEN or PRIVATE.