talk: the P2P chat from 1983 that a VPN brought back to life

en.andros.dev · 2026-08-21 · by Long Nguyen ·generic
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…

talk: the P2P chat from 1983 that a VPN brought back to life

:quality(85)/https://andros.dev/media/thumbnails/lorenzo-herrera-p0j-mE6mGo4-unsplash.jpg)

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:

    1. Ana's `talk` first asks (`LOOK_UP`) Bob's `talkd` whether Bob had already invited her, in case both are calling at the same time. Since there is nothing (`NOT_HERE`), it continues. 2. Ana's `talk` leaves an invitation on its own `talkd`, pointing to the TCP port where it will listen. 3. Ana's `talk` sends an `ANNOUNCE` to Bob's `talkd`. That daemon writes the famous notice on Bob's terminal: "talk: connection requested by ana@host". 4. Bob types `talk ana@host`. His client asks (`LOOK_UP`) Ana's `talkd` where she is listening. 5. Ana's `talkd` returns 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 `talk` connects 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.

    Screenshot of NeoTalk, with the contact list and a conversation in bubbles: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 the talkd(8) one. The split-screen behaviour and the daemon.
  • BSD reference manual (title.urm), which credits `talk(1)` to Clem Cole, Kipp Hickman and Peter Moore.
  • protocols/talkd.h, the BSD header with the `CTL_MSG` and `CTL_RESPONSE` structs, 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.
  • mesg and wall on Wikipedia, for the earlier family of commands.
  • The IBM 7094 and CTSS, by Tom Van Vleck, on the CTSS `WRITE` command 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
  • License by-nc-nd:quality(85)/https://andros.dev/static/img/components/license/by-nc-nd.png)

    This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.

    How did I use AI in this article?

    Do you want to read what I never publish?

    I send what does not fit in the articles: full configurations, messy notes and whatever I am testing right now. No spam, no sales funnels.

    Send an email to newsletter@andros.dev with the subject SUBSCRIBE and you are in.

    Subscribe by email

    To unsubscribe, send UNSUBSCRIBE to the same address.

    Help me keep writing

    Every coffee gives me a push toward the next article.

    Ko-fi donationsSure, it's on me!

    Comments

    Leave a comment

    There are no comments yet.

    You may also like

    [](https://en.andros.dev/blog/49eb5b06/migrate-notes-from-standard-notes-to-joplin/) New Joplin:quality(85)/https://andros.dev/media/thumbnails/ai_thumbnail_49eb5b06.png)

  • mac
  • linux
  • software
  • Migrate notes from Standard Notes to Joplin

    30 December 2017 [](https://en.andros.dev/blog/54572bc7/finger-the-1971-social-network-that-never-died/) Finger:quality(85)/https://andros.dev/media/thumbnails/franco-antonio-giovanella-Lzys6r1xFD8-unsplash.jpg)

  • linux
  • gemini
  • python
  • opensource
  • orgsocial
  • indieweb
  • Finger: the 1971 social network that never died

    18 August 2026 [](https://en.andros.dev/blog/ba142044/twtxt-vs-org-social-the-evolution-of-an-idea/) Org Social:quality(85)/https://andros.dev/media/thumbnails/org-social.png)

  • emacs
  • org-mode
  • twtxt
  • orgsocial

twtxt vs Org Social: the evolution of an idea

6 May 2026

en.andros.dev · 21 images · 1 videos · 36 links

Comments (0)

No comments yet