> ## Documentation Index
> Fetch the complete documentation index at: https://tesser.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# See any branch at localhost

> Every box has an address; bare localhost is the boxes you have focused, port by port

tesserd is a small proxy on your laptop. It gives every box its own address
and makes bare `localhost` behave like the laptop were the boxes you are
looking at.

`tesser dev`, `use`, and `review` start it in the background when it is not
running, and `tesser daemon install` makes it a login service (see
[the daemon](https://tesser.sh/docs/cli-reference.md#tesser-daemon)). It listens on port 3000 for its own
panel and status page, and on every port any of your boxes declares or
depends on. A port means that port everywhere: nothing is ever redirected to
some other port of some other box.

tesserd only answers requests addressed to a name that reaches this machine:
`localhost`, any `*.localhost` name, an IP address, the machine's hostname or
`<hostname>.local`, and its Tailscale name when Tailscale is running. A
request with any other `Host` header gets a 403 that asks you to open
`localhost:<port>` instead. If you put a proxy of your own in front of
tesserd, have it send `Host: localhost`.

## Every box has an address

```text theme={"theme":"css-variables"}
http://box-<id>.localhost:<port>
```

This is what `tesser dev` prints, with the port the service listens on
(3000 for a typical Next.js app). A box id such as `box_a1b2c3` appears in
its address as `box-a1b2c3`, because a Content-Security-Policy does not
accept a hostname with an underscore. The `box_a1b2c3.localhost` spelling
still reaches the same box. Browsers resolve `*.localhost` to your own
machine without any configuration, so two tabs on two box ids show two
branches side by side. Every port a box declares is a door, such as
`box-<id>.localhost:9229` for a debugger port. A port the box does not
declare answers 404.

A box's dependency ports are doors as well. If a frontend box's manifest says
`5000 = "api"`, then `box-<id>.localhost:5000` is the `api` that frontend is
talking to: the box you wired it to, or the org's shared instance, whichever
its routing table says right now. When that backend is one of your own boxes
the request rides the tunnel the laptop already holds to it; otherwise the
daemon opens one through the frontend box's own loopback port. A dep with
nothing behind it answers 503 and names the `tesser wire` command that fixes
it.

A page opened on a box's address stays with that box when it calls bare
`localhost`. If the page at `box-<id>.localhost:3000` fetches
`http://localhost:8080`, loads a script or image from it, or opens a
websocket to it, tesserd sends the request where `box-<id>.localhost:8080`
would go, so a URL your app has baked in stays in that box's worktree.
tesserd recognizes these requests by their `Origin` header, or `Referer` when
there is no `Origin`. A port outside that box's declared and dependency ports
goes to the focused box, as described below. Page loads on bare `localhost`
are never routed this way, and moving the focus does not reload these tabs or
close their sockets.

### From a box

The same address works on the boxes themselves. Code running on any of your
boxes can open `http://box-<id>.localhost:<port>` for any other instance
box in the org and reach that box's declared port, whether or not the two
are wired together. Workbenches declare no ports, so they have no address,
and a box holds addresses for at most 254 others. It works for a browser or curl on the box too, which never ask the
resolver about `*.localhost` and dial plain loopback with the name in `Host`:
on a port some other box declares, that connection is routed by the name, the
way the laptop does it. Nothing is bound on the box for this, and anything
that listens on the box wins its port, whether it started before or after:
the box's own ports, its dependency ports, a database a test brought up. So
from a browser on a box, a peer's copy of a port something on this box is
listening on reaches this box, not the peer. The other way round, a port some
other box declares accepts a connection on this box's loopback even when
nothing local is listening, so a raw TCP probe (`nc -z`, `wait-on tcp:`)
cannot tell that port is free; probe over HTTP instead. A port the other box
does not declare is refused immediately. This includes the
shared instances of `main`: a shared box can call back into a dev box that
handed it its address, which is how a dev box registers for webhooks. The
run command gets that address as `TESSER_BOX_URL` (and the id as
`TESSER_BOX_ID`), so a run script does not need to work it out.

### A name that follows the shared instance

A box id names one box for as long as it lives. On a box,
`<service>.localhost:<port>` names whichever box is currently the org's
shared instance of that service, so it survives a promote: the name moves to the new box and the superseded
one drains. Use it when the other side is meant to be the shared instance
rather than a particular box, such as a webhook subscription that should
keep working across deploys. In-flight connections are not moved; a new
connection after the promote lands on the new box.

## Bare localhost is the focused boxes, port by port

Selecting a box selects its entire recursive dependency graph. Each box brings
its declared ports and dependency ports. Shared dependencies are included even
when you do not have a local target or SSH key for them: the daemon tunnels
through one of your registered boxes using its access to the box mesh.

For a dashboard wired to a server, where the server uses hp and a worker:

| Choice | Dashboard | Server | hp and worker |
| - | - | - | - |
| Use dashboard A | A | A's server | A's dependencies |
| Use server B | stays A | B | B's dependencies |
| Use hp C | stays A | stays B | hp C; worker stays unless hp C depends on another worker |
| Use dashboard A again | A | A's server | A's dependencies again |

The last explicit selection wins for every port in its subtree. Unrelated
ports remain where they were. Remove a selection to reveal the previous
selection underneath it. A missing binding fails with an explanation; it
does not silently fall back to an older selection. Shared nodes and cycles
are visited once per selected root.

This changes your laptop's routes. Dashboard A's remote server process still
calls the backend wired to A. To browser-test a backend-only branch B, run a
personal dashboard B and wire it to backend B, even if its frontend code is
unchanged. See [Wiring a dependency](https://tesser.sh/docs/wiring.md#wiring-a-dependency).

### Databases and other TCP

Anything that speaks on a port works. A dependency that is a database is
reachable from laptop tooling on bare `localhost:5432` just as the box
reaches it: HTTP on a door is routed by name, everything else is passed
through as bytes.

### Cookies and OAuth callbacks

Moving the focus does not change the bare address, so an OAuth callback
registered for `localhost:3000` keeps working as you move between branches.
Cookies stay with the address too, exactly as they would for two local copies
of your app on one port: if each box keeps sessions in its own database, the
next box will ask you to sign in again. A box's own address has its own
cookies, so a tab opened there keeps a sign-in per box. `localhost` and
`box-<id>.localhost` are different sites to the browser, so a `Lax` or
default cookie is not sent between them. A `SameSite=None` cookie set on
`localhost` is sent along with a box page's calls to bare `localhost`, and
those calls reach the page's box rather than the focused one. When the focus moves,
the proxy closes the old box's connections on the ports that moved, so a
hot-reload socket that was talking to one branch does not keep feeding the
page after you have moved to another; pages on ports that did not move are
not touched.

### The panel

The square in the bottom-right corner opens the panel (`⌘⇧U`), which lists
the branches serving this port; hover it to see which branch you are on.
"Hide until tesserd restarts" at the bottom of the panel takes the square off
every page; `⌘⇧U` still opens the panel, and expired AWS credentials still
show.
Choose a branch to select the service serving this page and its complete
dependency graph. Selecting the current branch again restores its graph after
overrides.

A tab keeps the kind of address you opened it on. On a box's address,
choosing a branch moves the tab to that branch's box,
`http://box-<id>.localhost:<port>`, on the same path; every box keeps its own
cookies there, so a sign-in on one branch survives a visit to another. On
bare `localhost` the address stays and the page reloads onto the chosen
branch.

A service whose manifest sets `box_address = true` never stays on bare
`localhost`: a page you open there moves to the box that port shows,
`http://box-<id>.localhost:<port>`, on the same path. Only page loads move.
Once the page is on the box's address, its API calls and sockets to bare
`localhost` reach that box, as described in
[Every box has an address](#every-box-has-an-address).

Ports that fail to connect are listed under the branches.

Bare `localhost` follows the choice either way, so a URL your app has baked
in (`http://localhost:8080` for its API, say) reaches the branch you are
looking at.

To a browser, a page on a box's address and an API on bare `localhost` are
different sites, and it will not send that API's cookies. If your frontend
calls its API at a hardcoded `http://localhost:<port>` and signs in with
cookies, point it at its box's address, `http://box-<id>.localhost:<port>`, instead and set
`box_address = true`, or serve the API through the dev server's proxy so the
page only talks to its own origin.

### From a terminal

From a terminal:

```sh theme={"theme":"css-variables"}
tesser use box_dashboard_B          # select its complete graph
tesser use box_server_C             # override the server subtree
tesser use --off box_server_C       # reveal dashboard B's choices
tesser use                         # inspect destinations and availability
tesser use --json                   # the same graph/status the panel reads
```

Selection is saved even if the daemon is unavailable; the command then fails
and says routing was not verified. It also fails when the selection is applied
but its routes are unavailable. A ready route means the local tunnel accepts
connections and the last known box status permits serving; it is not an
application-level health check.

A new `tesser dev` joins the selection at the bottom, taking unclaimed ports.
Re-running an existing box preserves its priority. Starting a service does
not rewire its dependencies or launch other services.

## Over Tailscale

The daemon answers requests from your own machine and from Tailscale peers,
so a phone or a second laptop on your tailnet can open the proxy's address and
see the same focus. It refuses requests from the rest of your LAN unless you
start it with `--allow-lan`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.