Skip to content

Processes and IPC ​

Pond is four programs. They talk over Unix sockets in the Pond folder, which is ~/.pond unless POND_HOME points elsewhere.

The processes ​

Pond.app ​

The app you see. It draws the blobs, the stage, the sidebar and the browser tile, and it is the only process that writes the sealed settings. It is not sandboxed. Its only entitlement is outgoing network access.

pond-ptyd ​

The terminal helper. It owns every pseudo-terminal, so your agents keep running when Pond quits, crashes or updates.

  • One thread and one poll() loop, with no timers while nothing happens.
  • Started on demand and detached. There is no LaunchAgent.
  • One helper per Pond folder, held with a lock file.
  • It exits by itself 10 minutes after its last terminal ends.
  • Terminal output lives only in memory, in a 2 MB ring per terminal. It is never written to disk or logged, and the ring is zeroed when a terminal is dropped.
  • At most 32 terminals and 16 clients at once. A request line is at most 64 KB.
  • Each terminal's shell is started with only the three standard descriptors (0 to 2). Every other descriptor the helper holds is closed in the child.
  • Each shell gets the umask Pond was launched with, normally 022, not the helper's own 077. Files an agent creates in your repo then get the same modes as in a normal terminal, while the helper's own socket, lock and files stay private.

When Pond starts again it lists the terminals, subscribes and reattaches. If the helper itself dies, Pond restarts it at most 3 times a minute, with a growing delay. It then offers to resume the agents that were lost.

The pond CLI ​

The pond command. You run it in a shell. Claude Code runs it too:

  • pond hook for each Claude Code hook event of a session Pond started;
  • pond browser-mcp, pond computer-mcp and pond mcp as stdio MCP servers. Each one is a thin proxy that forwards tool calls to Pond.app or Pond Computer and keeps no state of its own.

pond hook never slows Claude Code down. It prints nothing, reads its input for at most half a second, waits for the helper for at most 250 ms, and exits 0 on every error.

Pond Computer.app ​

An optional helper for computer use. It holds Accessibility and Screen Recording, so Pond.app never needs them. It starts only when an agent with computer use calls a tool, and quits 2 minutes after its last client. See Computer use.

The sockets ​

Pond's sockets and who may connectFive Unix sockets live in the Pond folder, each mode 0600. pond-pty.sock is served by pond-ptyd and checks the peer's user, its code signature and its process ancestry. browser.sock is served by Pond.app and accepts only the signed pond CLI from the right agent's terminal. computer.sock is served by Pond Computer.app and accepts only the signed pond CLI for a live agent. feed.sock is served by Pond.app and checks the user and the agent's terminal ancestry. preview.sock is served by Pond.app for this user only.Socket (mode 0600)Served byChecked before the first byte is readpond-pty.sockpond-ptydsame user, signed code path,and which agent terminal it runs underbrowser.sockPond.appsame user, the signed pond CLI,called from that agent's own terminalcomputer.sockPond Computer.appsame user, the signed pond CLI,for an agent pond-ptyd says is livefeed.sockPond.appsame user, called from thatagent's own terminalpreview.sockPond.appsame userPond.app also checks that pond-pty.sock is served by its own signed pond-ptyd.

All sockets are mode 0600 in a folder that is mode 0700. The helper binds its socket under umask 077, sets 0600, and checks the result before it listens.

The app's four sockets (preview, browser, feed and computer) are bound privately, with no change to the process-wide umask. A shared function makes a fresh folder next to the final path (mode 0700, never looser), binds the socket inside it, sets 0600, and renames it into place in one step that never replaces an existing entry. If something is already at that name, the bind fails. The temporary folder is removed on every path. The umask is not switched around the bind because it applies to the whole process, and a file another thread made at that moment would come out stricter than intended.

Every protocol is newline-delimited JSON, one answer line per request line. Errors come back as fixed sentences. Nothing from a terminal, a request or a path is echoed into an error.

Who is on the other end ​

A same-user check alone is not enough on a Mac where agents run as you. Any agent shell could connect and type into another terminal. So the servers ask the kernel three things about each peer:

  1. The user. getpeereid must return your user id.
  2. The code. The peer's audit token (LOCAL_PEERTOKEN) leads to its code on disk. Its running signature must be valid, and its path must be the expected one: Pond.app, Pond Computer.app or the pond binary inside the same bundle.
  3. The ancestry. The peer's pid (LOCAL_PEERPID) and its parents show whether it runs under an agent's terminal, and under which one.

What a peer may do then depends on who it is:

Peerpond-pty.sock allows
Pond.app (signed, expected path)everything, including your own keystrokes
A process under an agent's terminalguarded writes into its own terminals only, and hook for its own terminal
Pond Computer.appcomputer events only

A guarded write is refused while you have unsent text in that terminal, or while Claude Code may be showing a dialog. An agent can never type over your draft or answer a permission prompt for you.

It works the other way too. Before Pond.app or the CLI sends anything, it checks that pond-pty.sock is served by its own signed pond-ptyd. What the server says about itself is never used for that check.

Protocol versions ​

The helper reports its protocol version in ping. After an update, a helper started by the old build keeps serving its terminals. Features that need a newer version, such as starting an agent, say so until that helper exits after its last terminal. The next start uses the new binary.

Pond is not released yet. These docs describe the current build.