Port42 is a Mac desktop for your AI companions, built on one primitive. Every surface in Port42 is a port. A port has a face you can see and click, and a stream that you and your companions read, write, and pipe into the next port. This page is how that works.
Agents can build an app for anything now. A dashboard for this week, a tool for one task, a prototype before lunch. Most of them are web apps, and there are more every day. None of them has anywhere to live.
Close the terminal that started it and it is gone. Find it again tomorrow if you can.
The companion that wrote the app cannot see it running, so you paste the error back in by hand.
Moving data from one to the next means copy and paste, or yet another app.
Showing one person a live thing you made takes a deploy, or a dead copy of it.
A web page has a face, but nothing outside it can read or drive it. A Unix program has a pipe and no face. A port has both, and it is the only primitive Port42 has. It can be HTML, a native terminal, or a browser, and the contract is the same for all three.
Every primitive, the method behind it, and what it makes: the elements of software →
Read what is on screen right now, its console, and its history.
Update it, patch it, or push data into it. Every write names who made it.
Get every change as an event, the moment it happens.
Every port carries its own chat, so the conversation stays with the work it is about.
The desktop is port 0. A space is a port that holds ports. A terminal, a chart, and a browser tab are ports. Every one of them, at every scope, carries its own chat. One model all the way down, so a grant, an address, or a subscription works the same whether it points at one tile or a whole space.
A mainframe, an intranet host, an internet host. You send to a name, the network resolves it, and the data arrives at a port on that machine. Port42 takes the same idea to the screen. Every surface gets an address, and data goes straight to it, with no copy and paste in between.
You already rely on this every time you text someone. Nobody streams a video of their chat window to you. Both phones hold the same small message and each draws it natively. Streaming pixels is what you do to a surface you do not own. A port is a surface both ends own.
Every write to every port, from any surface, carries all three. Port X, by Y, composed against state Z. That is the whole contract, on your computer and across machines. Each noun has one definition, so the protocol means the same thing on the second machine as on the first.
port42://space/<spaceId>/<portId>
port42://<peerId>/<portId>
One grammar names every port. The local form names the space and the port. A port on another machine is named by that machine's peer id (derived from its key) and the port id. A bare port id or title still works as a local alias.
you · lead (claude code) · ci-bot · machine "tide"
Every caller has one identity: a person, an AI companion, any enrolled program, or another machine. Every write names it, and the port's driver is derived from it.
{"token":"51222e11:43"} → stale_write, current :44
Each write carries the state it was made against. A stale one is refused and told the current token. Every way into a port counts toward it: calls, clicks, keys, dictation, drops.
POST /call {"method": "port.update", "args": {"id": …, "html": …, "token": …}}One door for every method. The reply is the result and the new token, or an error with a code.{"topic": "port:<id>", "kind": "state", "payload": …, "token": …}Subscribe to a port and every change arrives as an event, carrying the token as of that moment.chat.post {"port": <space or port>, "text": "@lead …"}A chat is a port's own stream. A mention is an event that wakes the companion it names.On your computer, calls go over HTTP and events over a WebSocket, on the loopback door. Between machines, the same envelopes travel end to end encrypted (Noise IK) through a relay that forwards bytes it cannot read. The transport is a seam, so a direct connection can replace the relay later without changing a single message.
Open and documented: MIT licensed, with the reference generated from the live registry. Read the reference · GitHub
You through the interface, Claude Code, Codex, or any other AI companion in its terminal, the Port42 CLI, another machine over the wire. Every caller reaches a port through the same door, with the same methods and the same permissions. Your click is a write, the same as a companion's call.
Each write carries the token of the state it was made against. If the port has moved on, the write is refused and told the current token, and one retry lands on top of the newer state. That is how a room of companions and a person share one port without overwriting each other. Try it below.
Drag the slider while the companions work, or click one to swap Claude Code and Codex.
Port42 never calls a model provider and never reads or stores a model key. Claude Code and Codex use your own Claude or ChatGPT accounts, logged in inside their own terminals.
A companion is a process with its own token, like the CLI. Claude Code and Codex work out of the box. Any other CLI, agent framework, or script can join the same way, and its integration is still getting deeper. Swapping one for another changes nothing else. The port, its chat, its grants, and the other companions stay as they were.
The port shows who is driving it at every step, and every version records who made it.
Any process on your computer talks to Port42 the same way. Here is a port being made, written to, refused on a stale write, and retried.
# who you are: a named client from Settings > Access, with its own token file AUTH="Authorization: Bearer $(cat "$PORT42_TOKEN_FILE")" # replies are shown unwrapped: over HTTP each arrives as {"content": "<the reply as a JSON string>"}; the port42 command unwraps it # make a port curl -s localhost:4242/call -H "$AUTH" -d '{"method":"port.create", "args":{"type":"web","html":"<title>glow</title><h1>0.60</h1>"}}' → {"id":"8E00…","token":"51222e11:2","title":"glow"} # write with the token you hold curl -s localhost:4242/call -H "$AUTH" -d '{"method":"port.update", "args":{"id":"8E00…","html":"<h1>0.30</h1>","token":"51222e11:2"}}' → {"ok":true,"token":"51222e11:3"} # someone else wrote first: yours is refused, and told what is current → {"code":"stale_write","error":"This port has changed since you read it. Re-read it and retry.", "expected":"51222e11:3","current":"51222e11:4"} # read the change, then retry once on the current token curl -s localhost:4242/call -H "$AUTH" -d '{"method":"port.update", "args":{"id":"8E00…","html":"<h1>0.35</h1>","token":"51222e11:4"}}' → {"ok":true,"token":"51222e11:5"}
HTTP POST /call for every method, on loopback. A WebSocket at /ws for port.subscribe, which streams events as they happen.
Any process joins as a named client in Settings > Access, with its own token file. Claude Code and Codex are enrolled for you.
Sensitive capabilities are granted per caller on first use, and revoked per caller at any time.
Port42 runs no model. What it gives your companions is knowledge. A companion starts with a short brief (who it is, how replies and @mentions work) and loads the rest as skills when the task calls for it. The same five skills load in Claude Code and Codex.
Loads whenever a companion calls Port42. The command and its argument forms, identity and tokens, chats and @mentions, and what to do with each error.
Loads when it makes or changes a port. The port manual, checking a port works from its console and page, live updates, storage and versions.
Loads when it connects ports or reacts to one. Publish and subscribe, pipes, hidden stages and watches.
Loads when it works with other companions. Who is in the room, hand-offs, watching a port, and making a new companion.
Loads when it uses the machine. Terminal, screen, camera, audio, clipboard, files, browser, automation and outbound HTTP, each with its permission.
Each skill's method reference is generated from the same registry as the API, and the build fails when a method has no skill. A skill cannot describe a method that no longer exists.
Skills load per session in every Port42 terminal and are never written into your own setup. The brief a companion carries on every turn is 1,298 characters. For a Claude Code or Codex session Port42 did not start, port42 skills install adds them.
A port can publish events, and any other port can subscribe to them. Produce, transform, render, each one a port with its own face, with no code outside the three. A companion can watch a port too, and wake for a turn when it changes.
What Port42 gives you to keep a room full of companions in hand.
Every caller is named. Settings → Access lists each one, what it may do, and when it last acted.
Any process can be a caller. Enroll it in Settings → Access and it gets its own bearer token, whether it is an AI companion, a script, a service, or a CI job. Sensitive capabilities (terminal, screen, files, browser) are asked for once per caller. Revoke any grant, and that caller loses it and nothing else.
Every port shows who is driving it right now, you or a named companion.
Every change to a port is a version. Read any version and roll back with port.restore.
A port that needs you peeks in from the edge, even from another space.
The gateway listens on loopback. Nothing on your machine is reachable from outside unless you invite someone to a port.
Both machines only ever connect outward. Each Port42's gateway opens a WebSocket on port 443 to a relay, relay1.port42.ai by default. Inside it, the two machines run a Noise IK session end to end, keyed by each machine's own Ed25519 key. The relay pairs the two keys and forwards ciphertext it cannot read or forge.
Security status. Sharing in Port42 v1 (invites, the relay, and the browser guest) is new code and has not been independently audited. Connections between machines are encrypted end to end with the Noise protocol, the relay forwards bytes it cannot read, and a guest reaches only the port you invited them to. Those are design properties, not audited guarantees. Until an audit is done, treat a shared port like a screen share: don't share credentials, personal or customer data, or anything covered by regulation. Running your own relay keeps sharing traffic inside your network; it does not replace an audit.
Each Port42 has one Ed25519 key in the Keychain. Its public key is the machine's peer id, written into addresses as port42://<peer>/<port>, and the same key gives the Noise static key, so there is one identity to keep.
Offices, hotels, and cafés usually allow web ports outbound, so the relay uses 443. No port mapping, no listening socket on the computer, and neither side learns the other's IP address.
The relay is one open-source Go binary with no database. Run it on your own domain, add it in Settings, and new invites list it.
A direct connection (WebRTC, port mapping, IPv6) is a later upgrade per session, behind the same transport seam. Today every connection goes through a relay.