Skip to main content
Your worktree moves from your laptop to a box over SSH and nowhere else. The control plane at api.tesser.sh receives ids, ports, and states. It NEVER receives a file, a diff, terminal output, or your app’s traffic. For an org that runs its boxes in its own AWS account, the code exists in two places: your laptops and your account. A snapshot is the one copy that leaves the boxes: it stores a builder box’s home directory, with the checkout in it, in an S3 bucket. For an org in Tesser’s cloud that bucket is Tesser’s; for an org in its own AWS account it is a bucket in that account.

Every hop

The control plane has no upload endpoint. A box’s only channel to it is a WebSocket whose upward messages are hello, heartbeat, and a short list of events, none of which carries a file.

The SSH connection

Each laptop has one ed25519 key pair, generated with ssh-keygen the first time you sign in and stored beside your credentials in ~/.config/tesser/. The private half never leaves that directory. The public half goes to the control plane once, on your membership, and the control plane decides which boxes it belongs on: your own boxes, every box if you are an org admin, every shared instance, a box a CI job or hosted agent launched on your behalf, and a teammate’s box while they share it with you. A CI job or hosted agent that signs in through a grant registers its own key, which lasts only as long as its token. boxd receives that whole set over the box’s WebSocket and writes it as ~/.ssh/authorized_keys, replacing the file each time, so a key that stops belonging there leaves it. sshd on the box accepts nothing else: no password, no cloud-init key, no key the control plane did not place. Every ssh and rsync the CLI runs uses IdentitiesOnly=yes with that key, BatchMode=yes so an agent never hits a prompt, and a per-box known_hosts file with StrictHostKeyChecking=accept-new: the first connection records the box’s host key and every later one must match it. Nothing touches your ~/.ssh. Through Session Manager the host key is filed under the instance id instead of an IP.

What sync sends

sync, exec, and dev ship the files git would: tracked files plus untracked files that are not ignored, as one explicit file list to rsync. Ignored paths such as node_modules, .env.local, and build output stay on the laptop unless the manifest’s env.files names them. Removals are exact paths from the previous list rather than --delete, so the box’s own build state survives. The box’s .git is built from your clone. The CLI remembers which refs the box holds, packs only the git objects the box lacks, and streams the pack over SSH into git index-pack on the box. A fresh box gets your branch’s commits since the default branch, plus the default branch’s tip; afterwards the CLI sends up to 100 older commits in the background. The box never fetches from GitHub and has no git credential. A shared instance works the same way. tesser make api --ensure-running <sha> sends that commit as a pack and checks it out on the box; only the files the manifest’s env.files names ride rsync, from your worktree. The control plane is told the sha, not the commit.

What the control plane receives

  • Box metadata. Ids, class, service name, size, owner, power state, IP addresses, and the commit sha of a shared instance.
  • Service manifests. The TOML text of each manifest, which holds ports and the setup and dev commands and is committed to your repository.
  • Your public key, on the way to the box.
  • boxd heartbeats and events. Whether the dev server is running, its pid, exit code, which ports are listening, whether the health check passes, and how many SSH sessions are active. Events add when setup finished, the status and time of the first page the server answered, the sizes of node_modules and build caches, CPU, memory, and disk pressure, and the outcome of a boxd update.
  • Crash snapshots and the last log line. When a dev server exits, boxd sends the last 40 lines of its output with the exit event so tesser dev can say why. While a dev server runs, boxd also reports the last line of its output, cut to 300 characters, and when the app crashes under a file watcher or another process holds its port, the last 20 lines. These are the only places program output reaches the control plane. An org in its own AWS account turns them off with tesser cloud connect --no-crash-output: the control plane then keeps the exit code and none of the output lines, and tesser dev points at tesser logs, which reads the log file over SSH.
  • Snapshot records. Each snapshot’s id, repository, commit sha, sizes, state, and, for a failed build, a short reason. The setup log stays on the builder box, and the image goes to the bucket.
  • Routing tables and wires. Which box each dependency port points at.
  • Values set with tesser env set, stored in the org and placed in the environment of the service’s boxes and of workbenches from the same repository. An org in its own AWS account can keep them in its Parameter Store instead: the control plane then writes each value once, keeps the key’s name, and never reads a value; the boxes read them themselves. Env files pushed to a dev box go over SSH and are not among them.
  • Usage. When each box was awake, with its size, service, and owner.
  • API token hashes.
Not on the list: file contents, diffs, commits, the output of exec, ssh, or logs, HTTP traffic to a dev server, and the contents of any env file that was pushed or synced.

In a snapshot

A snapshot holds /home/ubuntu, /var/lib/docker, and /var/lib/containerd from the builder box after every setup ran: the checkout at the snapshot’s commit, node_modules and other installed dependencies, and whatever setup wrote. If setup writes a value from tesser env set to disk, the snapshot holds it too. Before the capture, the builder deletes the personal files listed under Snapshots, such as ~/.ssh/authorized_keys, ~/.git-credentials, and ~/.aws. Tesser’s bucket blocks public access, encrypts at rest with SSE-S3, and refuses requests not made over TLS. In Tesser’s cloud, boxes have no S3 credentials: the control plane signs a URL that expires within an hour for each object a box reads or writes. In your own AWS account it is the reverse: boxes reach your bucket with the boxes’ role, and the role Tesser assumes has no access to it.

On the box

The worktree lives at ~/workspace and the dev server’s output at ~/.tesser/dev.log. boxd acts only when told to: start or stop the dev server, rewrite its routing table, replace its authorized keys, set the env for shells, mount a repo’s snapshot when a pool box is claimed, and update itself. It has no message for reading a file. A start cannot name the command. A start message names only the service: boxd reads setup and dev from the <service>.toml in ~/workspace, the copy your own tesser sync or tesser dev put there, and runs those. That guarantee covers starts and wakes, and nothing more:
  • Env is the control plane’s to set (it holds what you gave tesser env set). boxd drops keys that load a program, such as NODE_OPTIONS, LD_PRELOAD, BASH_ENV, and PROMPT_COMMAND, along with the GIT_, NPM_CONFIG_, and similar families. That list is a denylist, so it covers the known hooks rather than every program’s.
  • A boxd update carries a program. The control plane tells boxd to update, and boxd fetches a new bundle from the control plane and runs it in place of itself, but only a bundle that carries Tesser’s release signature; the first boot of a box checks the same signature. The control plane chooses which signed release runs, not what is in it.
  • authorized_keys is the control plane’s to write, which is how it decides who may ssh in.
The root volume is EBS encrypted. When a box sleeps, it hibernates and writes its memory to that volume, so whatever your processes held in memory stays encrypted on the box’s own disk until it wakes. The instance’s user-data holds no credential: it is JSON naming the org, the box, and the control plane’s URL, and nothing executes it, because the image turns cloud-init’s user-data processing off and a boot step reads the JSON from the instance metadata endpoint. That endpoint stays on for the life of the box, IMDSv2 only, because the box’s AWS credentials come from it. boxd proves which box it is with a token from AWS STS GetWebIdentityToken: signed by AWS, valid for at most five minutes, naming the instance and its account, and addressed to the control plane. The control plane accepts a box’s WebSocket only with a token naming that box’s instance. In Tesser’s account, minting that token is the only thing the box’s instance role can do. Any process on the box can mint one, so code running on a box can speak to the control plane as that box: it receives that box’s routing table, env, and authorized keys, which are on the box already, and nothing of any other box. In Tesser’s account, the boxes of one org sit in a security group that admits port 22 from anywhere and, from the org’s own boxes, only port 14650, the port boxd forwards dependencies over. boxd passes a connection on that port through only to a port the box’s manifest declares, so another box never reaches anything else your app or a test listens on, and nothing reaches the group from another org. In your own account there is no port 22: the group admits only 14650, from the org’s own boxes and from a share gateway if you run one. Box-to-box traffic stays on private VPC addresses.

In your own AWS account

For a connected org, the instances, the disks, the code, the logs, and the box-to-box traffic are all in your account, and Tesser reaches it with a short-lived OIDC token rather than a stored credential. Boxes launch from Tesser’s published image, or from your own copy of it with the role pinned to that copy, and never run their user-data. There is no inbound port: the SSH stream, still encrypted end to end between your laptop and sshd, rides inside a Session Manager session that your IAM authorizes. What the control plane can do lists what it can still do to those boxes.