# CLI ↔ agent IPC

> How the routeup CLI talks to the background agent over a per-user Unix socket.

The CLI and the local agent are separate processes. They talk over a per-user
Unix domain socket, never a network port, so the local control plane is not
reachable off the machine.

## Transport

```txt
Transport:   Unix domain socket, one per user
Path:        ~/.routeup/agent.sock
             $XDG_RUNTIME_DIR/routeup/agent.sock on Linux when available
Permissions: 0700 directory, 0600 socket
Wire format: JSON over HTTP/1.1
Auth:        filesystem permissions only (no token on the local socket)
Versioning:  /v1/ URL prefix; GET /v1/status reports version and boot id
```

Filesystem permissions are the entire auth model here: only your user can read or
write the socket, so no token is needed for local control.

## API surface

```txt
POST   /v1/routes              register a route claim
DELETE /v1/routes/{name}       release a claim
GET    /v1/routes              list active routes
GET    /v1/owners/{name}       attach a serve-owner control stream
POST   /v1/owners/{name}/stop  request cooperative owner shutdown
POST   /v1/owners/{name}/ack   acknowledge stop receipt
GET    /v1/status              agent status, version, uptime, boot id
POST   /v1/shutdown            graceful shutdown
GET    /v1/logs?route=&follow= stream access logs (SSE)
GET    /v1/requests/{id}       inspect a retained request/response exchange
POST   /v1/expose              start public exposure for a claimed route
POST   /v1/unexpose            stop public exposure
```

## Why the registry can be in-memory

The status response carries a `boot_id` generated once per agent process. Live
CLI owners retain their exact desired state: serve and runner owners re-register
local claims; any owner with public exposure restores it; standalone expose
owners restore only their exposure. Foreground and detached owner processes are
the source of truth, so the agent never persists the route registry or tunnel
configuration to disk.

`routeup stop` uses the owner stream and acknowledgment endpoints. It never
signals a PID copied from the registry. Small non-secret runtime records contain
only record ID, route, owner kind, and PID so lifecycle commands can fail closed
while the in-memory agent is restarting; targets and credentials are not stored.

See [Local agent](/docs/concepts/local-agent) for the daemon side and
[Conflict resolution](/docs/architecture/conflict-resolution) for ownership
rules.
