tesser login writes the one
credential the CLI needs, and everything else is controlled by command-line
flags or environment variables.
Environment variables
Files on the laptop
Nothing is installed system-wide, and nothing requires root.
Ports on the laptop
The daemon answers requests from your own machine and from Tailscale peers.
It refuses the rest of the LAN unless it is started with
--allow-lan.
Timers
The box
Each box is a standard size (2 vCPU, 8 GB of memory) unless--size or the manifest picks small (1 vCPU, 4 GB), large (4 vCPU, 16 GB), or xlarge (8 vCPU, 32 GB), with a 40 GB gp3 disk at the gp3 default throughput of 125 MiB/s,
running Ubuntu 24.04 on its LTS kernel (6.8) with Node (22 and 24, via fnm),
Bun, rsync, and Docker (with compose and buildx) installed. Your worktree is at ~/workspace and the dev server’s output is
written to ~/.tesser/dev.log. Commands run as the ubuntu user, which has
passwordless sudo and is in the docker group.
The setup and dev commands, snapshot builds, tesser exec, and a command
line given to tesser ssh run on the Node version your repo pins. The box
looks for .nvmrc, .node-version, or engines.node in package.json,
starting in the command’s working directory and walking up, and the nearest
pin wins. A service’s commands start in its directory, and tesser exec
without --in starts at the repo root. When the pinned version is not
installed yet, the box installs it once and prints
tesser: installing the node that <dir> pins; the version stays installed while the box sleeps. When
there is no pin, or the pin cannot be installed, the command runs on the
box’s default Node and does not fail. After a failed install the box waits an
hour before it tries that download again. The dev log opens with a
tesser: node <version> line naming the version it used. The interactive
shell that tesser ssh <box_id> opens does not use this lookup.
The run command sees these variables from Tesserc:
TESSER_BOX_URL sits under anything you set with tesser env set; the other three are fixed per run.
A command run with tesser exec, or a command line given to tesser ssh, sees the same variables, with two differences. TESSER_BOX_URL is set only on a service box that one of this laptop’s worktrees started. TESSER_SLOT is set on a shared instance and on a dev box that one of this laptop’s worktrees started, and left out otherwise. The interactive shell that tesser ssh <box_id> opens gets none of them.
A service’s setup also runs on the snapshot builder, and the repo’s new boxes start from the disk it leaves behind (unless you pass --no-snapshot). On the builder, setup sees none of these variables. Anything specific to one box, such as its address, its id, or a per-box secret, belongs in dev and never in setup.