$ cd docs && ls
the manual
Everything the README knows, reformatted for the web: every flag, command, and key, plus the fixes for the problems people actually hit. ← back to the tour
$ man lanchat
man page
name
lanchat, the sshhh-lanchat client: ephemeral encrypted chat for the people on your Wi-Fi
synopsis
lanchat[-r room][-n nick][-k passphrase | -ask][-color][-stealth][-iface name][-ttl n]
environment
CHAT_KEY: the passphrase, without putting it on the command line (anything on the command line is visible in shell history and the process list).CHAT_DEBUG=1: received-packet diagnostics on stderr.
options
| -r, -room <name> | channel to join (default: lobby) |
| -n, -nick <name> | display name (default: your username) |
| -k, -key <phrase> | room passphrase; prefer -ask or CHAT_KEY over the command line |
| -ask | prompt for the passphrase without echoing it |
| -color | give every speaker a stable color of their own |
| -stealth | shell-style prompt, flat log lines, silent bell |
| -prompt <str> | custom input prompt (default: » ) |
| -iface <name> | pin a network interface (default: auto-detect, VPNs skipped) |
| -ttl <n> | multicast TTL (default: 1; traffic never leaves the local segment) |
| -no-broadcast | disable the directed-broadcast fallback |
| -no-bell | don't ring the terminal bell on new messages |
| -version | print the version and exit |
» /help
commands & keys
commands
| (just type) | send a message; the room sees it live |
| /who | list who's here right now |
| /nick <name> | change your display name (your color survives the rename) |
| /me <action> | send an action: * alice waves |
| /snooze [time|off] | pause the bell; 15 min by default, /snooze 1h30m works |
| /clear | clear the screen |
| /boss | hide behind fake build output |
| /quit | leave; there is nothing to log out of |
keys
| Tab | complete nicknames and commands; press again to cycle |
| Ctrl-B | instant boss key; any key restores, held messages replay |
| ↑ / ↓ | input history |
| Ctrl-A / Ctrl-E | jump to start / end of line (Home/End too) |
| Ctrl-U / Ctrl-W | clear the line / delete a word |
| Ctrl-L | clear the screen |
every arriving message rings the terminal bell: a red badge on the macOS Dock, a marked tab in iTerm2/tmux, a flashing taskbar on Windows. /snooze quiets it for 15 minutes, -no-bell for the whole session. stealth and boss mode never ring. when someone writes your name, the line is shown in bold.
$ lanchat --doctor # if only. here's the manual version
troubleshooting
“command not found: lanchat”
Almost always the terminal you installed from caching its old PATH. Open a new terminal (or run hash -r) and try again. Still failing? Run it once by full path to confirm it’s there:
$ ~/.local/bin/lanchat“we’re on the same Wi-Fi but can’t see each other”
- 1.same room and passphrase? a different passphrase is a different key: you simply can't read each other. open and private rooms of the same name don't mix.
- 2.firewall on first run, macOS asks to allow incoming connections and Windows prompts to allow the app; say yes (Private networks on Windows).
- 3.guest Wi-Fi / “AP isolation” many guest and public networks block clients from talking to each other. nothing on the device can fix that; use a trusted network.
- 4.multicast-filtering office Wi-Fi lanchat detects this (“couldn't join multicast” in the banner) and falls back to directed broadcast per subnet automatically. if the network blocks both, that's AP isolation in practice.
- 5.different subnets a campus “same Wi-Fi” can be several routed subnets. traffic stays on one segment by default (TTL 1, a privacy feature). if your network routes multicast, -ttl 4 lets frames cross.
- 6.VPN auto-detection skips tunnels, so a VPN no longer swallows chat traffic. to chat over a tunnel on purpose, pin it: -iface utun3.
- 7.still stuck? run with CHAT_DEBUG=1 to print received-packet diagnostics to stderr.
$ cat LIMITATIONS # by design
limitations, by design
- best-effort delivery
UDP can drop a packet on a congested network; a missed line is simply missed. That matches the ephemeral, no-storage model. Multicast + broadcast per subnet makes loss rare.
- one LAN segment
TTL 1 means frames don’t cross routers. Intentional: it’s a local chat. If your network routes multicast,
-ttl 4opts out. - multi-instance on macOS
Several windows on one Mac work, but which one receives a looped-back packet can be unreliable (shared-socket load-balancing). One instance per machine is unaffected.
$ cat FAQ.md
frequently asked
What is sshhh-lanchat?
A free, open source terminal chat for your local network. Everyone on the same Wi-Fi who runs lanchat with the same room and passphrase is in one conversation. There is no server, no account, and nothing is written to disk.
Does it need the internet?
No. Messages travel directly between machines on the LAN over UDP multicast, so it works on networks with no internet connection at all.
Is sshhh-lanchat encrypted?
Yes. Every datagram is encrypted with AES-256-GCM using a key derived from the room name and passphrase (PBKDF2, 210k rounds). Open rooms without a passphrase are readable by anyone on that LAN, and there is no identity or forward secrecy: it is a lightweight LAN tool, not Signal.
How do I install lanchat?
One command. macOS/Linux: curl -fsSL https://raw.githubusercontent.com/granthgg/sshhh-lanchat/main/scripts/get.sh | sh. Windows PowerShell: irm https://raw.githubusercontent.com/granthgg/sshhh-lanchat/main/scripts/get.ps1 | iex. The script verifies the SHA-256 checksum and puts lanchat on your PATH.
What is the boss key?
Ctrl-B instantly replaces the chat with plausible build output, so a glance at your screen reads as compiling, not chatting. Any key restores the chat, and messages that arrived while hidden replay.
Who created sshhh-lanchat?
Granth Gaurav. It is written in Go with zero third-party crypto and released under the MIT license.
$ git clone https://github.com/granthgg/sshhh-lanchat.git
development
make targets
| make build | build ./lanchat for this machine |
| make test | unit tests: crypto round-trip, room isolation, dedup, sanitizer |
| make vet | go vet ./... |
| make fmt | gofmt the tree |
| make cross | binaries for all desktop targets into dist/ |
Zero third-party crypto: encryption is Go’s standard library. The only dependencies are the official golang.org/x/{net, term, sys} packages. Releases are cut by pushing a version tag; CI cross-compiles every target, generates checksums.txt, and attaches everything to a GitHub Release.
deeper tours: ARCHITECTURE.md · RELEASING.md
package layout
| cmd/lanchat/ | CLI entry point: flags, usage, key resolution, wiring |
| internal/chat/ | composition root: builds a session and runs the loops |
| internal/crypto/ | key derivation, AES-256-GCM sealing, wire framing |
| internal/proto/ | message record, dedup, sequence numbers, sanitizer |
| internal/roster/ | presence tracking: who is here right now |
| internal/transport/ | UDP multicast + broadcast, interface selection |
| internal/ui/ | raw-mode line editor, thread-safe printer, boss-key decoy |