talk: the P2P chat from 1983 that a VPN brought back to life
Before the internet, people could already chat. It is a topic that has always intrigued me: how was it possible? As a kid I had already heard about a command called talk, and the most impressive part is that you can still use it today, with no sign-ups and straight from the terminal, even in workplaces where I work over a VPN. It is not dead: it is just that few people know its potential.
This article is to satisfy my own curiosity, and if someone learns something along the way: all the better. If you lived through the talk era and spot any inaccuracy, please write to me privately so I can fix it, since finding information has been hard.
How did people chat back then?
The way people chatted in the 80s does not resemble the experience we have today.
Two people shared the same screen and could watch each other type. I am not sure you realise what that means: in real time, letter by letter, each one saw how the other typed, deleted and hesitated. It was not a send-and-wait chat, but a living screen split in two.
Here you can see how the conversation is simulated with two Docker containers.
It all started by finding out whether the other person was available. For that you had the finger command, which told you if a user was connected and what they were doing. If you are interested, I have another article on what finger was and how it worked.
Then, if they were available, you ran the talk command in the terminal, followed by the user and host you wanted to talk to.
For example:
talk ana@library
ana would get a message in her terminal letting her know that someone wanted to talk to her. If she accepted, the screen split in two and the conversation began.
You were limited to talking with a single person at a time, and you needed an account on the same system as the other person, or on systems that could see each other: what you would call talking over a LAN today, a P2P communication with no central servers.
There was also no conversation history, no way to send files, and no authentication or encryption (anyone who could see the traffic could read it). It was a very basic chat, but a functional one.
The curious thing is that you can still do this today, and it works. The talk client ships out of the box on macOS and most Unix systems. On Debian or Ubuntu you install it with apt install talk talkd. Its daemon, ntalkd, is right there too.
Origin
It all began with two people who wanted to talk to each other through a machine they shared.
In 1965 MIT's CTSS had a WRITE command to send a line to another logged-in user, and systems like Multics, PLATO or NLS offered similar mechanisms.
In the 70s, Unix inherited and polished it. You copied lines of text straight onto another user's terminal. And to decide whether you wanted to be interrupted or not, there was mesg (from message), dated 3 November 1971, attributed to Dennis Ritchie and Ken Thompson. A mesg n and you closed the door; a mesg y and you opened it. There was also wall (write all), which shouted a message to every terminal at once. All quite crude by our standards, but shaped for its time.
The leap came in 1983 with 4.2BSD. That is where talk appeared as I have described it: split screen, simultaneous typing and, most importantly, able to connect two people on different machines across the network. It was no longer about talking to whoever shared your computer, but with anyone on a connected machine. The credit goes to Kipp Hickman, Clem Cole and Peter Moore.
The protocol
For two strangers on different machines to end up with their screens linked takes some engineering. There is no central server where both register, which forces a dance of requests. You need a middleman on each side: the talkd (or ntalkd) daemon.
Think of talkd as your machine's receptionist, with two jobs: it keeps the invitations you leave and notifies your users when someone from outside wants to talk to them:
- Negotiation (finding each other and ringing the doorbell) goes over UDP.
- The conversation itself, the stream of letters, goes over a direct TCP connection between the two clients.
To negotiate, clients and daemons send each other control messages:
LEAVE_INVITE(I leave an invitation)LOOK_UP(I look for an invitation)DELETE(I delete it)ANNOUNCE(notify that person). With those four pieces the whole thing is built.
The conversation between Bob and Ana looks like this:
sequenceDiagram
participant A as Ana's talk
participant DA as Ana's talkd (UDP)
participant DB as Bob's talkd (UDP)
participant B as Bob's talk
A->>DB: LOOK_UP (has Bob invited me yet?)
DB->>A: NOT_HERE (not yet)
A->>DA: LEAVE_INVITE (I'm listening on this TCP port)
A->>DB: ANNOUNCE (notify Bob)
DB->>B: "talk: connection requested by ana@host. Reply with: talk ana@host"
B->>DA: LOOK_UP (where is Ana listening?)
DA->>B: Ana's TCP address
B->>A: direct TCP connection
Note over A,B: From here on, live text over TCP
Step by step:
- Ana's
talkfirst asks (LOOK_UP) Bob'stalkdwhether Bob had already invited her, in case both are calling at the same time. Since there is nothing (NOT_HERE), it continues. - Ana's
talkleaves an invitation on its owntalkd, pointing to the TCP port where it will listen. - Ana's
talksends anANNOUNCEto Bob'stalkd. That daemon writes the famous notice on Bob's terminal: "talk: connection requested by ana@host". - Bob types
talk ana@host. His client asks (LOOK_UP) Ana'stalkdwhere she is listening. - Ana's
talkdreturns her TCP address. Bob connects directly to Ana, and the conversation begins.
All the port exchange travels inside those control messages. The address where each client listens is placed in a field of the message (addr) and passed from hand to hand.
Few more elegant solutions have been seen in the history of computing.
ntalk to unite them all
The control message carried the network address inside a C struct that was sent exactly as it sat in memory. And it turns out not all machines store bytes in the same order, what is called endianness.
Endianness is the way a computer stores the bytes of a number. A little-endian stores the least significant byte first, and a big-endian does the opposite. For example, the number 0x12345678 is stored like this:
- Little-endian: 78 56 34 12
- Big-endian: 12 34 56 78
This made it impossible to talk between machines from different vendors. A talk between two machines of the same type worked without a hitch. But between a little-endian and a big-endian, each read the other's address as, well, a pile of meaningless bytes! talk depended on byte order.
In short, you only talked to people with your same architecture. And you wanted to talk to everyone!
The solution was ntalk, the new version of the protocol. It added a version field and ordered the bytes properly so any two architectures could understand each other. To avoid breaking the old one, each version stayed on its own port:
- The original
talk(sometimes called otalk): UDP port 517. - The new
ntalk: UDP port 518.
This caused other problems, like clients speaking 518 to a daemon that only understood 517, or the other way around. Typical were the endless hangs with checking for invitation on caller's machine, or the your party is using an incompatible version of the talk program.
Variants came out to plug the gaps. ytalk, by Britt Yenne, was the first to allow more than two people at once (groups) and to talk between different architectures. utalk skipped TCP and sent even the conversation over UDP.
Each one solved a shortcoming of the original, a step forward.
So when someone mentions talk, they probably mean ntalk, which is what most modern Unix systems ship.
By the way, there is not even an RFC for talk. It is Unix folklore, not a blessed specification.
Why it did not survive the modern internet
talk was designed for an internet that no longer exists: one where every machine had a public IP address, a name, and trusted the others. As soon as that world changed, the protocol lost the ground beneath its feet.
The problems, one by one:
- Only two at a time. Base
talkconnects exactly two people. No groups, no rooms. - NAT kills it. The protocol hands the other side a specific IP and port and expects you to connect directly to that address. Behind a home router, that address leads nowhere.
- The firewall blocks it. It needs inbound UDP 517/518 and, on top of that, inbound TCP connections to high ports on both ends. Any reasonable firewall cuts it off.
- Zero security. Plain text, no encryption and no authentication. Your identity was, literally, the username you were typing into the packet.
- No history. If you disconnect, the conversation is lost. There is no record of what was said.
- No nicknames. Only Unix accounts. If you do not have an account on your friend's machine, you cannot talk to them.
- No servers. There is no central point to register at, nor to leave messages if you are offline. If your friend is not at their machine, there is no way to reach them.
And forget about sending files, video calls or emojis.
On the other hand, in 1988 Jarkko Oikarinen created IRC, which solved many of these problems: without depending on a specific machine and without the compatibility headaches. It quickly relegated talk to a corner of history.
VPN, a new hope
The protocol works perfectly; what breaks it is the network around it: NAT, firewalls, the lack of reachable addresses... problems of who can reach whom.
And what exactly does a modern mesh VPN do? WireGuard, Tailscale or ZeroTier set up a private network where every machine has a stable, reachable address again for all the others, with a bonus it never had: the tunnel is encrypted!
Over that overlay network, ntalkd on UDP 518 and the TCP connection back work again exactly like in 1983. The IP the daemon hands the other side is now routable. NAT and the firewall sit below the tunnel. talk has no idea forty years have gone by.
Now you just need to find a friend curious or geeky enough. Fire up a VPN, start ntalkd and talk to them. You will rediscover how strange and beautiful it is to watch someone type live from the terminal.
NeoTalk
Another approach: what if we adapt the idea to a modern setting, with a language like Python? I built a quick prototype to see if it was possible, and it is. You can find it in this repository.
:quality(85)/https://andros.dev/media/blog/2026/08/neotalk.png)
It keeps the critical parts: negotiation over UDP and the conversation over a direct TCP connection between the two clients, just like in 1983. But it removes the thorns:
- Graphical interface with the list of who is online and the conversation in bubbles.
- End-to-end encryption (X25519 + AES-GCM). Privacy no longer depends on the network, though it pairs beautifully with a VPN.
- Aliases instead of Unix accounts. Pick whatever name you like; you do not need an account on the other machine.
- Message-based typing. With a "typing…" indicator, but without exposing every keystroke like the original did.
- Automatic discovery on the local network and over a VPN (WireGuard, Tailscale…), announcing itself by unicast or by dialing the address directly.
In the end it is just a very basic P2P chat over IP. It is not trying to compete with anything, but it is a proof of concept to show that the idea behind talk is still great nearly half a century later.
Final notes
I hope you have enjoyed this trip through the history of talk. It is still amazing that it stays installed by default on many systems and remains functional in certain setups.
It is another example of how technology can be incredibly clever and, at the same time, fragile in the face of changes in its environment. But it is not dead for that reason: we have the tools to keep it working if you are interested.
Sources
Every fact in this article comes from these references:
- talk (software) on Wikipedia. History, the arrival in 4.2BSD, ntalk, ytalk and utalk.
talk(1)man page (FreeBSD) and thetalkd(8)one. The split-screen behaviour and the daemon.- BSD reference manual (
title.urm), which creditstalk(1)to Clem Cole, Kipp Hickman and Peter Moore. protocols/talkd.h, the BSD header with theCTL_MSGandCTL_RESPONSEstructs, the message types and response codes.- The talk protocol, Henning Schulzrinne's notes on the rendezvous, the control messages and the byte-order dependency.
- Building Internet Firewalls (O'Reilly). The UDP-to-negotiate, TCP-to-converse split, and ports 517 and 518.
mesgandwallon Wikipedia, for the earlier family of commands.- The IBM 7094 and CTSS, by Tom Van Vleck, on the CTSS
WRITEcommand in 1965. - Jarkko Oikarinen on Wikipedia and his own account of the birth of IRC in 1988.
- draft-hunter-talk-00, the (expired) IETF draft documenting the talk protocol.
- Tailscale and its comparison with ZeroTier, for the overlay, addressable network model that revives
talk.
- How did people chat back then?
- Origin
- The protocol
- ntalk to unite them all
- Why it did not survive the modern internet
- VPN, a new hope
- NeoTalk
- Final notes
- Sources
This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.
Help me keep writing
Every coffee gives me a push toward the next article.
Sure, it's on me!
Comments
There are no comments yet.