tesser --help and every
tesser <command> --help, regenerated from the CLI at each release, so what
your agent reads on the box is what you read here.
tesser
Usage: tesser [options] [command]
persistent cloud boxes for dev servers, tests, and builds; the code stays local
Options:
-v, --version output the version number
-h, --help display help for command
Commands:
version print the CLI version
licenses show bundled rsync's license and extract its complete source
login [options] [target] sign in through the browser or through a grant, and make the chosen org the default
logout revoke the saved token and forget it
whoami [options] the signed-in email, where the org and token came from, and when the token expires
org the org every command runs against
member the org's members (admins only)
grant rules that let an agent platform or CI job sign in as a service account (admins only)
cloud [options] run the org's boxes in your own AWS account
gateway [options] serve shared boxes at box-<id>.<host>, from Cloudflare or from inside the org's own AWS account
skill the agent skill: a few lines that point at --help
boxd the agent tesser runs on each box
daemon [options] run the local proxy in the foreground: box-<id>.localhost, bare localhost for focused boxes, the panel, and the tunnels
use [options] [box_id...] focus boxes, last one on top: bare localhost:<port> shows their ports
make [options] [service] create a box and print its id: a workbench, or an instance box for a service
pool booted boxes kept warm for an hour after the last make so make takes seconds
snapshot disk snapshots of a repo after every service's setup; new boxes start from the current one
ls|list [options] list the org's boxes, a sortable table in a terminal
top the org's boxes and wiring, live, in a terminal UI
status [options] [box_id] one box in detail; with no id, the current worktree's box
usage [options] the org's meter: credit left, what is awake, and time by size and service
spend-limit [options] [dollars] the most usage past what the plan includes that a month may bill; bare form shows it
update [options] [version] install the latest CLI release, then restart a running daemon on it
sync [options] [box_id] copy the current worktree to a box; with no id, the current worktree's box
env env files on boxes, and the values held for a service's shared instances
exec [options] [box_id] sync the worktree and run a command on a box (the worktree's workbench when no box is named)
dev [options] [service|box_id] start a service's dev server from the current worktree
wait [options] [box_id|service] block until a box's dev server is healthy, or exit non-zero with why it never will be
logs [options] [box_id] the dev server's output; with no id, the current worktree's box
sleep [options] <box_id> power a box down; any command targeting it wakes it
wake <box_id> power a box up and wait until it answers
util [options] <box_id> a box's cpu (% of all vcpus) and memory over time, one row per step, kept 7 days
sleep-after [options] [duration] how long your instance boxes sit idle before they sleep; bare form shows it
keep [options] <box_id> never let a box sleep or expire on its own; only when the user asks, never for a long job
ssh <box_id|service> [command line...] an interactive shell in ~/workspace, or one command there (no sync first); a service name means its org default box
rm [options] <box_id...> remove boxes and their disks; wires that pointed at them fail loud until re-wired
share [options] <box_id> a review link for a box and everything it depends on; anyone in the org opens it with tesser review
review <link> open a review link: the box and its deps get addresses on this laptop
wire [options] <box_id> [service] [target_box_id] point a box's <service> dependency at a box, or back to the org's shared instance; bare form shows every dep
service the org's service registrations
nuke [options] remove every box in the org, plus every service registration and shared instance; env values survive
help [command] display help for command
How it works
The code stays on the laptop; the compute is a cloud box. tesser mirrors
the current git worktree to a box's ~/workspace and runs commands there.
Every box has a fixed address on the laptop, http://box-<id>.localhost:<port>,
served by tesserd. `dev`, `use`, and `review` start it in the background
when it is not running. If a box address refuses connections, run
`tesser use` with no arguments: it starts tesserd and reports each route.
`cloud` and `daemon install` are the human's to run, never yours.
Each worktree gets a workbench for `exec` (tests, typechecks, builds) and
one instance box per service for `dev`. Boxes persist until `rm` and keep
their node_modules; idle ones sleep, and any command targeting one wakes it
(about a minute). A long job belongs in `tesser exec` run as a background
task on your side, never nohup on the box: a detached job does not count as
activity, so the box sleeps under it. `keep` is the user's call, not yours.
`tesser ls` finds a box whose id you lost; its last column is the worktree
each box belongs to. Boxes run Ubuntu with Node, Docker, and passwordless
sudo; install anything else with `exec`. A workbench runs no service's
setup: install from the lockfile with `exec` when dependencies are missing
or their inputs changed, and keep what is already there.
Start here
tesser exec -- pnpm install workbench: setup, tests, typechecks
tesser exec -- pnpm test
BOX=$(tesser dev web) instance box; tell the human the address it prints
tesser sync "$BOX" ship edits; HMR picks them up. --restart for a new dependency
tesser logs "$BOX" -f dev server output (Ctrl-C detaches)
tesser rm "$BOX" when the worktree is done
Pick the smallest check. A test or typecheck runs on the workbench with
nothing else up. Start a service only when the behavior needs a running
stack, and only the services that check needs.
Every command explains itself: tesser <command> --help.
Contracts
`make` and `dev` print the box id as their only stdout; progress goes to
stderr. `exec` and `logs` pass the remote exit code through. Read
commands take --json. Everything after -- is exact argv; no shell parses
it. Chain with -- bash -c 'a && b'.
`dev` blocks until the service is healthy, or exits non-zero with the
reason when it cannot be; it always exits on its own. Run it in the
foreground, or as a background task and wait for that task to exit; after
`tesser dev --detach`, `tesser wait <box>`. Never poll instead: no curl
loop on its URL, no `pgrep -f`/`pkill -f` of a string in your own
command line (it matches your own shell), no loop grepping its output.
Signed out, run `tesser login`: it prints a link for the human and exits.
Send it to them; once they have authorized it, `tesser login --wait`
finishes.
Give the human the box's own URL printed by `dev`. They choose which box
bare localhost:<port> shows from the panel on every page. `top` and bare
`usage` are terminal UIs for a person, never for an agent.
When something fails
Save the command, box id, worktree, sha, and the full error. Then check one
layer at a time: boxd is connected (`tesser status <box>`), its server
runs (`tesser logs <box>`; a box that exists is not a server that
runs), its deps point where you think (bare `tesser wire <box>`), then
your own data. A slow phase is not a hung one: read its progress before
calling it stuck, and never `rm` it or start a duplicate. If one
recovery fails, stop and report the blocker instead of replacing boxes or
rerunning a broad suite.
Done: hand off the worktree and sha, each box and its role, the wires, the
test data, the command, where its log is, and its exit code. Once the human
has what they need, or the worktree is done, remove the data you seeded and
`tesser rm` the boxes this task made, your subagents' included.
Never
Edit files on the box. The next sync overwrites them; `ssh` is for looking.
Commit on the box. It is a shallow mirror of the local HEAD; commit locally.
--force past the sync guard. It means the box belongs to another worktree;
`make` a new one.
Let the dev server drift ports. Pin the port in its config so a collision
fails loud instead of breaking routing.
Touch a box you did not make. `dev`, `sync`, `wire`, `sleep`, and `rm`
on someone else's box restart their server or repoint their deps. To use
their box, wire yours to it.
Rebuild, re-pin, or restart a shared instance. When one is missing or
unhealthy, report the service, box, and error. `make --ensure-running`
and `boxd update` on one are the human's call; ask first.
Seed, change flags on, or delete data you did not create. Shared instances
hold every worktree's data; make your own uniquely named tenant (org,
workspace, project) inside the app.
Run `tesser use` unless the human asks. It changes what their localhost
shows; the box URL from `dev` is what you hand them.
`rm` never confirms and is unrecoverable.
tesser version
Usage: tesser version [options]
print the CLI version
Options:
-h, --help display help for command
tesser licenses
Usage: tesser licenses [options]
show bundled rsync's license and extract its complete source
Options:
-h, --help display help for command
tesser login
Usage: tesser login [options] [target]
sign in through the browser or through a grant, and make the chosen org the
default
Arguments:
target oidc to exchange an id token through a grant
Options:
--org <org_id> require this org instead of showing the picker
--token <tsr_api_…> save a token made on the dashboard instead of opening a
browser (needs --org)
--grant <grt_id> with oidc: the grant to exchange through (needs --org);
inside GitHub Actions the CLI mints the id token itself,
elsewhere pass --proof
--proof <command> with oidc: a shell command that prints an id token for
audience {audience}; rerun whenever the CLI needs a
token, for tesser or AWS
--no-browser print a link to open in any browser instead of opening
one here (the default for agents and over ssh)
--wait finish a login whose link was handed to someone: wait for
them to authorize it
-h, --help display help for command
tesser logout
Usage: tesser logout [options]
revoke the saved token and forget it
Options:
-h, --help display help for command
tesser whoami
Usage: tesser whoami [options]
the signed-in email, where the org and token came from, and when the token
expires
Options:
--json
-h, --help display help for command
tesser org
Usage: tesser org [options] [command]
the org every command runs against
Options:
-h, --help display help for command
Commands:
ls|list [options] the orgs this laptop is signed in to
use <org_id> make one of them the default
Every command runs in one org; `login` makes the org it authorized the
default. TESSER_ORG=<id> overrides for one shell.
tesser org ls
Usage: tesser org ls|list [options]
the orgs this laptop is signed in to
Options:
--json
-h, --help display help for command
tesser org use
Usage: tesser org use [options] <org_id>
make one of them the default
Options:
-h, --help display help for command
tesser member
Usage: tesser member [options] [command]
the org's members (admins only)
Options:
-h, --help display help for command
Commands:
ls|list [options] list members
add <email|service:name> [role] invite an email address, or create a service
account service:<name>
role <membership_id> <role> change a member's role
rm|remove <membership_id> remove a member and revoke every token they
hold
alias issuer claims that name a member, so a token
exchanged through a grant is attributed to
them
token tokens held by a service account
Admins only. `member add <email>` invites one address. `member add
service:<name>` makes a service account: a
member that never signs in and holds tokens and grants instead. It is
always a member, never an admin. `member token create <membership_id>
--name ci --expires 30d` mints it a token, printed once; `member token ls`
and `rm` manage them. A human mints their own tokens on the dashboard.
An alias pins an issuer claim to a member: `member alias set <membership_id>
https://app.devin.ai requesting_user_email <email>`. When an agent platform
or CI job signs in through a grant (tesser grant --help), the box it makes
is recorded as made for the member the claim names; an alias is for when
the claim does not already match the member's email.
tesser member ls
Usage: tesser member ls|list [options]
list members
Options:
--json
-h, --help display help for command
tesser member add
Usage: tesser member add [options] <email|service:name> [role]
invite an email address, or create a service account service:<name>
Arguments:
email|service:name
role admin or member (choices: "admin", "member", default:
"member")
Options:
-h, --help display help for command
tesser member role
Usage: tesser member role [options] <membership_id> <role>
change a member's role
Arguments:
membership_id
role admin or member (choices: "admin", "member")
Options:
-h, --help display help for command
tesser member rm
Usage: tesser member rm|remove [options] <membership_id>
remove a member and revoke every token they hold
Options:
-h, --help display help for command
tesser member alias
Usage: tesser member alias [options] [command]
issuer claims that name a member, so a token exchanged through a grant is
attributed to them
Options:
-h, --help display help for command
Commands:
set <membership_id> <issuer> <claim> <value> pin an issuer claim to a member
rm|remove <membership_id> <issuer> <claim> <value> drop one alias
help [command] display help for command
tesser member alias set
Usage: tesser member alias set [options] <membership_id> <issuer> <claim> <value>
pin an issuer claim to a member
Arguments:
membership_id
issuer https://app.devin.ai, token.actions.githubusercontent.com, …
claim requesting_user_email, actor_id, …
value
Options:
-h, --help display help for command
tesser member alias rm
Usage: tesser member alias rm|remove [options] <membership_id> <issuer> <claim> <value>
drop one alias
Options:
-h, --help display help for command
tesser member token
Usage: tesser member token [options] [command]
tokens held by a service account
Options:
-h, --help display help for command
Commands:
create [options] <membership_id> mint a token for a service account;
printed once
ls|list [options] <membership_id> list a member's tokens
rm|revoke <membership_id> <token_id> revoke one token
help [command] display help for command
tesser member token create
Usage: tesser member token create [options] <membership_id>
mint a token for a service account; printed once
Options:
--name <name> what holds it: ci, the machine it lives on
--expires <duration> 30d, 12h, 90m; 1h..365d
--role <role> cap the token below the account's role (choices:
"admin", "member")
-h, --help display help for command
tesser member token ls
Usage: tesser member token ls|list [options] <membership_id>
list a member's tokens
Options:
--json
-h, --help display help for command
tesser member token rm
Usage: tesser member token rm|revoke [options] <membership_id> <token_id>
revoke one token
Options:
-h, --help display help for command
tesser grant
Usage: tesser grant [options] [command]
rules that let an agent platform or CI job sign in as a service account (admins
only)
Options:
-h, --help display help for command
Commands:
create [options] <devin|replicas|github:owner/repo> let an issuer's id tokens be exchanged for a service account's tesser token
ls|list [options] list the org's grants
rm|revoke <grant_id> revoke a grant; no more exchanges
Admins only. A grant is a rule, not a secret: id tokens from one issuer
whose claims match the grant's pins may be exchanged at the control plane
for a tesser token acting as one service account until the grant expires.
Its id can sit in a workflow file or an agent's config. Grants are org-
level and always for a service account (tesser member --help); without
--for, one named after the issuer (devin, replicas, github-actions) is used and made
if missing. A person who wants an agent to act as themselves pastes their
own token instead: tesser login --token, or TESSER_TOKEN.
tesser grant create devin --pin org_id=<devin org id>
tesser grant create replicas --pin organization_id=<replicas org id>
tesser grant create github:acme/web pins repository; add --pin ref=refs/heads/main
The command prints the id and the exact `tesser login oidc --org <org>
--grant <id>` line for that issuer. In a GitHub Actions job with
`permissions: id-token: write` the CLI mints the id token itself; for
Devin and Replicas the line carries `--proof '<command>'`, a command that
prints an id token for `{audience}`, which the CLI fills in: the control
URL to exchange, sts.amazonaws.com for AWS. Either way the CLI proves again
and exchanges again when the token is near expiry or is refused, one process
at a time. Boxes an agent session makes show its client and session,
`devin · <session>`, are recorded as made for the person the id token
names, and show in that person's dropdown. `grant rm` stops new
exchanges; tokens already minted last until they expire, an hour at most.
When the org runs boxes in its own AWS account, `--aws-role <arn>` names a
role the agent assumes with the same proof (audience sts.amazonaws.com), so
it needs no AWS setup of its own. The role trusts the issuer, with conditions
mirroring the pins, and allows Session Manager to the org's boxes. `tesser
login oidc` writes AWS profile tesser-<org> with a credential_process that
proves and assumes again whenever AWS asks, and makes it the org's profile.
That never asks tesser, so `grant rm` does not end AWS access; the role's
trust policy does.
tesser grant create
Usage: tesser grant create [options] <devin|replicas|github:owner/repo>
let an issuer's id tokens be exchanged for a service account's tesser token
Options:
--for <membership_id> the service account to act as; without it, one named
devin, replicas, or github-actions, made if missing
--name <name> a label; defaults to the issuer and pins
--expires <duration> 30d, 12h; 1h..365d (default: "90d")
--aws-role <arn> a role in the org's AWS account the agent assumes with
the same id token; `tesser login oidc` sets it up as
the AWS profile for the org's boxes
--pin <claim=value> an extra claim the id token must carry (repeatable)
(default: [])
-h, --help display help for command
tesser grant ls
Usage: tesser grant ls|list [options]
list the org's grants
Options:
--json
-h, --help display help for command
tesser grant rm
Usage: tesser grant rm|revoke [options] <grant_id>
revoke a grant; no more exchanges
Options:
-h, --help display help for command
tesser cloud
Usage: tesser cloud [options] [command]
run the org's boxes in your own AWS account
Options:
--json print JSON
-h, --help display help for command
Commands:
status [options] where the org's boxes run, and AWS errors from
the last 7 days
connect [options] check an AWS account and move the org's boxes
there (flags default to the current config once
connected)
check [options] test the connected account end to end, or a
candidate given with the connect flags, without
storing anything
disconnect return the org to tesser's cloud (once it has no
boxes)
template [options] the IAM policies and network rules the org's AWS
account needs
aws-profile [options] [name] this laptop's ~/.aws profile for the org's SSM
sessions, overriding the org's --aws-profile
Admins only, and only when the human asks. The account is set up with the
Pulumi program in the self-hosting docs (tesser cloud template prints the
policies it holds); once it is applied, tesser cloud connect --account <id>
--region <region> checks the account end to end and moves the org there.
tesser cloud check runs the same checks any time. Self-hosted boxes are
reached only through AWS Session Manager. When `ssh` fails asking for an
AWS profile, no profile is set: the org's default is
tesser cloud connect --aws-profile <name>; a laptop overrides it with
tesser cloud aws-profile <name>.
tesser cloud status
Usage: tesser cloud status [options]
where the org's boxes run, and AWS errors from the last 7 days
Options:
--json print JSON
-h, --help display help for command
tesser cloud connect
Usage: tesser cloud connect [options]
check an AWS account and move the org's boxes there (flags default to the
current config once connected)
Options:
--account <id> the AWS account the Pulumi program ran in; finds
its role, instance profile, subnet, and security
group
--region <region>
--role <arn> IAM role tesser assumes
--subnet <id>
--sg <id> security group
--private reach boxes at their private IP
--instance-profile <name> launch boxes with this IAM instance profile;
laptops reach them through Session Manager
--image <ami> launch your own copy of a tesser image, or `tesser`
for tesser's published one
--aws-profile <name> the ~/.aws profile members' laptops use for Session
Manager, unless a laptop sets its own
--sso-start-url <url> the AWS access portal behind that profile
(https://d-1234567890.awsapps.com/start); laptops
missing the profile get it written
--sso-region <region> the region of that IAM Identity Center
--sso-role <name> the permission set members sign in with in the
org's account
--no-sso forget the SSO portal
--env <store> where `tesser env set` values live: tesser
(default) or parameter-store, your account's
Parameter Store under /tesser/<org id>/
--max-boxes <n> the org's own box cap
--crash-output boxd sends a crashed dev server's last 40 log lines
to tesser so `tesser dev` can print them (the
default)
--no-crash-output keep them on the box; `tesser dev` points at
`tesser logs` instead
--snapshots-bucket <name> the S3 bucket in your account that holds repo
snapshots (`tesser snapshot create`), or `none`
--json print JSON
-h, --help display help for command
tesser cloud check
Usage: tesser cloud check [options]
test the connected account end to end, or a candidate given with the connect
flags, without storing anything
Options:
--account <id> the AWS account the Pulumi program ran in; finds
its role, instance profile, subnet, and security
group
--region <region>
--role <arn> IAM role tesser assumes
--subnet <id>
--sg <id> security group
--private reach boxes at their private IP
--instance-profile <name> launch boxes with this IAM instance profile;
laptops reach them through Session Manager
--image <ami> launch your own copy of a tesser image, or `tesser`
for tesser's published one
--aws-profile <name> the ~/.aws profile members' laptops use for Session
Manager, unless a laptop sets its own
--sso-start-url <url> the AWS access portal behind that profile
(https://d-1234567890.awsapps.com/start); laptops
missing the profile get it written
--sso-region <region> the region of that IAM Identity Center
--sso-role <name> the permission set members sign in with in the
org's account
--no-sso forget the SSO portal
--env <store> where `tesser env set` values live: tesser
(default) or parameter-store, your account's
Parameter Store under /tesser/<org id>/
--max-boxes <n> the org's own box cap
--crash-output boxd sends a crashed dev server's last 40 log lines
to tesser so `tesser dev` can print them (the
default)
--no-crash-output keep them on the box; `tesser dev` points at
`tesser logs` instead
--snapshots-bucket <name> the S3 bucket in your account that holds repo
snapshots (`tesser snapshot create`), or `none`
--json print JSON
-h, --help display help for command
tesser cloud disconnect
Usage: tesser cloud disconnect [options]
return the org to tesser's cloud (once it has no boxes)
Options:
-h, --help display help for command
tesser cloud template
Usage: tesser cloud template [options]
the IAM policies and network rules the org's AWS account needs
Options:
--account <id> fill in this account id
--region <region> fill in this region
--image <ami> pin the launch policy to your own copy of the image
--box-role <name> the IAM role inside the boxes' instance profile,
with its path if any, when it differs from the
profile's name
--snapshots-kms-key <arn> the KMS key the snapshots bucket encrypts with,
when it is not SSE-S3
--json print JSON
-h, --help display help for command
tesser cloud aws-profile
Usage: tesser cloud aws-profile [options] [name]
this laptop's ~/.aws profile for the org's SSM sessions, overriding the org's
--aws-profile
Options:
--clear forget the profile
-h, --help display help for command
tesser gateway
Usage: tesser gateway [options] [command]
serve shared boxes at box-<id>.<host>, from Cloudflare or from inside the org's
own AWS account
Options:
--json print JSON
-h, --help display help for command
Commands:
set [options] point `tesser share` at a gateway: a Cloudflare Worker behind
Access, or an AWS one with its own IAM role
off stop trusting the gateway; share links stop carrying a
gateway url
serve [options] run the AWS gateway behind its load balancer and proxy shared
boxes over their mesh
On tesser's cloud every shared box already answers at
https://box-<id>.tesser.review/ for the org's members, who sign in with
tesser in the browser; nothing to set up. tesser gateway set puts an org's
boxes on its own domain instead.
Admins only. A share gateway makes every shared box answer at
https://box-<id>.<host>/, where <host> is the gateway url's host. The box's
first declared port is served there, every other port at
https://box-<id>--<port>.<host>/, and pages rewrite their localhost:<port>
calls, links and redirects to match. The dev server sees the address it has
on a laptop, localhost:<port>. A visit wakes a sleeping box, with a page that
shows the progress, and traffic keeps it awake. A box is served only while
it has a live share (tesser share <box>); --revoke or expiry takes it off.
Two kinds, set with tesser gateway set:
Cloudflare (--access-team, --access-aud): a Worker in your own Cloudflare
account, behind a Cloudflare Access application on *.<host>. Access does
the user auth. Each shared box dials the Worker over an outbound websocket
with a ticket tesser signs, so nothing reaches into the boxes' network, and
the Worker holds no secret: it wakes a box with the viewer's Access token.
A revoke takes the box off within seconds.
AWS (--role): a process in the org's own AWS account (tesser gateway
serve), behind an internal Application Load Balancer with an ACM
certificate for *.<host>. It reaches boxes on their private IPs, proves
itself with its IAM role's AWS web identity token (the account needs
outbound identity federation, and the role sts:GetWebIdentityToken for the
tesser API's audience), and does no user auth: put it behind the VPN or an
SSO proxy. A revoke takes the box off within 15 seconds.
tesser gateway set
Usage: tesser gateway set [options]
point `tesser share` at a gateway: a Cloudflare Worker behind Access, or an AWS
one with its own IAM role
Options:
--url <url> the https base URL boxes hang off, like
https://share.example.com
--access-team <team> Cloudflare: the Zero Trust team domain, like
acme.cloudflareaccess.com
--access-aud <tag> Cloudflare: the audience tag of the Access application
in front of the gateway
--role <arn> AWS: the IAM role the gateway runs as, in the account
the boxes run in
--json print JSON
-h, --help display help for command
tesser gateway off
Usage: tesser gateway off [options]
stop trusting the gateway; share links stop carrying a gateway url
Options:
-h, --help display help for command
tesser gateway serve
Usage: tesser gateway serve [options]
run the AWS gateway behind its load balancer and proxy shared boxes over their
mesh
Options:
--org <id> the org whose shared boxes to serve
--bind <address> the address to listen on (default: "0.0.0.0")
--port <port> the plain HTTP port the load balancer forwards to (default:
"8080")
-h, --help display help for command
tesser skill
Usage: tesser skill [options] [command]
the agent skill: a few lines that point at --help
Options:
-h, --help display help for command
Commands:
install [options] write it to ~/.claude/skills/tesser-cli/SKILL.md, or into a
directory
help [command] display help for command
tesser skill install
Usage: tesser skill install [options]
write it to ~/.claude/skills/tesser-cli/SKILL.md, or into a directory
Options:
--dir <path> install into this directory
-h, --help display help for command
tesser boxd
Usage: tesser boxd [options] [command]
the agent tesser runs on each box
Options:
-h, --help display help for command
Commands:
update [options] <box_id> install the control plane's current agent on a box;
its dev server restarts under the new one
help [command] display help for command
`dev`, `sync`, and `exec` bring the agent on the box they target up to
the control plane's version first, restarting its dev server, and say so on
stderr. `boxd update` does the same for one box on purpose, including a
shared instance (admins only); `tesser status` shows the version a box
runs. If it says boxd did not come back, the update did not land within a
minute and the box is still on its old agent: retry, and if it fails again
tesser ssh <box_id> -- journalctl -u tesser-boxd -n 50 says why.
tesser boxd update
Usage: tesser boxd update [options] <box_id>
install the control plane's current agent on a box; its dev server restarts
under the new one
Options:
--yes the user asked for this on a box you did not make
-h, --help display help for command
tesser daemon
Usage: tesser daemon [options] [command]
run the local proxy in the foreground: box-<id>.localhost, bare localhost for
focused boxes, the panel, and the tunnels
Options:
--port <n> the daemon's own port (default: 3000)
--host <hostname>
--allow-lan also answer the rest of the local network, not only this
machine and Tailscale peers
-h, --help display help for command
Commands:
install [options] run it as a login service (launchd on macOS, systemd --user
on Linux) that survives reboots and crashes
uninstall remove the login service and stop the daemon it runs
stop stop a foreground or background daemon; a login service
needs uninstall
Nobody has to run this. `dev`, `use`, and `review` start tesserd in the
background when it is not answering, on TESSER_DAEMON_PORT (3000), logging to
<state dir>/daemon.log; `daemon stop` ends it. `daemon install` makes it a
login service instead (launchd on macOS, systemd --user on Linux) that comes
back after reboots and crashes and picks up `tesser update` on its own;
`daemon uninstall` removes it. Bare `tesser daemon` runs it in this
terminal, for watching it.
If something else holds port 3000, --port 3300 moves the viewport and `dev`
says which port to open. A local process already bound to a declared port
wins over the box's door silently: lsof -i :<port>.
tesser daemon install
Usage: tesser daemon install [options]
run it as a login service (launchd on macOS, systemd --user on Linux) that
survives reboots and crashes
Options:
--port <n> the daemon's own port (default: 3000)
--allow-lan also answer the rest of the local network
-h, --help display help for command
tesser daemon uninstall
Usage: tesser daemon uninstall [options]
remove the login service and stop the daemon it runs
Options:
-h, --help display help for command
tesser daemon stop
Usage: tesser daemon stop [options]
stop a foreground or background daemon; a login service needs uninstall
Options:
-h, --help display help for command
tesser use
Usage: tesser use [options] [box_id...]
focus boxes, last one on top: bare localhost:<port> shows their ports
Options:
--off unfocus instead
--json with no box ids, the daemon's routes as JSON
-h, --help display help for command
tesser make
Usage: tesser make [options] [service]
create a box and print its id: a workbench, or an instance box for a service
Options:
--ensure-running <sha> the org's shared instance of the service at this
commit
--size <size> (choices: "small", "standard", "large", "xlarge")
-h, --help display help for command
A workbench (no service) or an instance box for a service. Claims a
prewarmed pool box of its size in seconds when one exists (tesser pool
--help), else cold-boots in about 90s. A box in a repo with a snapshot
starts from it (tesser snapshot --help); without one, setup installs from
scratch.
--size picks RAM and CPU. Standard is 2 vCPU and 8 GB; each step doubles. A
manifest's `size` sets the default.
--ensure-running <sha> runs the org's shared instance of the service at a
commit (resolved in the current worktree), waits for it to be healthy, and
switches the org over to it. This creates shared instances, not personal
boxes. `tesser service ls` shows every one.
If the org is at its box limit, `tesser rm` an idle box; `tesser sleep`
does not help, since the cap counts boxes, not awake ones.
tesser pool
Usage: tesser pool [options] [command]
booted boxes kept warm for an hour after the last make so make takes seconds
Options:
-h, --help display help for command
Commands:
target [options] [n] keep N booted boxes of a size warm; 0 turns them off
ls [options] list unclaimed pool boxes
drain remove every unclaimed pool box
help [command] display help for command
`pool target` keeps booted boxes of a size that any make, exec, or dev
in the org claims. A claim in a repo with a snapshot mounts the snapshot
on the claimed box and starts from it while it fills in.
Unclaimed pool boxes self-destruct an hour after the last make they could
serve, and after 6 hours whatever happens.
tesser pool target
Usage: tesser pool target [options] [n]
keep N booted boxes of a size warm; 0 turns them off
Arguments:
n 0-8 (default: 2)
Options:
--size <size> (choices: "small", "standard", "large", "xlarge", default:
"standard")
-h, --help display help for command
tesser pool ls
Usage: tesser pool ls [options]
list unclaimed pool boxes
Options:
--json
-h, --help display help for command
tesser pool drain
Usage: tesser pool drain [options]
remove every unclaimed pool box
Options:
-h, --help display help for command
tesser snapshot
Usage: tesser snapshot [options] [command]
disk snapshots of a repo after every service's setup; new boxes start from the
current one
Options:
-h, --help display help for command
Commands:
create [options] build a snapshot of this repo at a commit: a
fresh box runs every service's setup, then its
disk is captured
ls [options] this checkout's repo's usable snapshots (the
org's outside a checkout), newest first
show [options] <snapshot_id> a snapshot
rm <snapshot_id> remove a snapshot; boxes made from it keep
running
help [command] display help for command
tesser snapshot create
Usage: tesser snapshot create [options]
build a snapshot of this repo at a commit: a fresh box runs every service's
setup, then its disk is captured
Options:
--sha <commit> the commit to snapshot (default HEAD)
--wait wait until it is ready or failed, streaming the setup log
-h, --help display help for command
tesser snapshot ls
Usage: tesser snapshot ls [options]
this checkout's repo's usable snapshots (the org's outside a checkout), newest
first
Options:
--all every repo in the org
--removed include removed and purged snapshots
--json
-h, --help display help for command
tesser snapshot show
Usage: tesser snapshot show [options] <snapshot_id>
a snapshot
Options:
--json
-h, --help display help for command
tesser snapshot rm
Usage: tesser snapshot rm [options] <snapshot_id>
remove a snapshot; boxes made from it keep running
Options:
-h, --help display help for command
tesser ls
Usage: tesser ls|list [options]
list the org's boxes, a sortable table in a terminal
Options:
--json
-h, --help display help for command
tesser top
Usage: tesser top [options]
the org's boxes and wiring, live, in a terminal UI
Options:
-h, --help display help for command
tesser status
Usage: tesser status [options] [box_id]
one box in detail; with no id, the current worktree's box
Options:
--json
-h, --help display help for command
Presence is boxd's socket; instance is whether the dev server is actually
up: none, exited, or running on :3000 (healthy). Trust the instance column,
not presence.
tesser usage
Usage: tesser usage [options]
the org's meter: credit left, what is awake, and time by size and service
Options:
--json
-h, --help display help for command
tesser spend-limit
Usage: tesser spend-limit [options] [dollars]
the most usage past what the plan includes that a month may bill; bare form
shows it
Arguments:
dollars 50, 12.50
Options:
--off no limit: bill all usage as you go
-h, --help display help for command
Pro and Team bill usage past what the plan includes. The spend limit caps
that extra, per month: when the org reaches it, its awake boxes sleep and
launches and wakes are refused until an admin raises it or the month resets.
Hobby has no extra to cap; it already stops at its included usage. Admins
only. Do not change it unless the user explicitly asks.
tesser update
Usage: tesser update [options] [version]
install the latest CLI release, then restart a running daemon on it
Arguments:
version a release to install instead of the latest
Options:
--check only say whether a newer release exists
-h, --help display help for command
tesser sync
Usage: tesser sync [options] [box_id]
copy the current worktree to a box; with no id, the current worktree's box
Options:
--restart run the manifest's setup and dev again after the sync
--detach with --restart, return once the run starts; `tesser wait <box>`
then waits for the port
--force sync even if it would delete most of the files on the box
--yes the user asked for this on a box you did not make
-h, --help display help for command
Respects .gitignore, so .env.local never reaches the box on its own. Either
list it under [env] files in the manifest (then every sync ships it) or send
it once with `tesser env push <box_id>`. After a push or an edit:
tesser sync <box_id> --restart.
The guard: syncing worktree B to a box made from worktree A would replace
its whole workspace. Do not --force past it; `make` a new box. A shared
instance's checkout is immutable and refuses sync entirely.
The box's repo is a shallow mirror of the worktree's HEAD. `git status`,
`diff`, and `rev-parse` behave normally; `git log` shows one commit, and
any commit or branch made on the box is wiped by the next sync.
tesser env
Usage: tesser env [options] [command]
env files on boxes, and the values held for a service's shared instances
Options:
-h, --help display help for command
Commands:
push [options] <box_id> [file...] send gitignored .env* files to a box (every one at the worktree root, or the files named)
set [options] <service> [KEY=VALUE...] set values for a service's shared instances
unset <service> <KEY...> drop values
ls <service> the names set, and required names still unset
help [command] display help for command
Two different things. `env push` sends gitignored files from the worktree
to one box (default: every gitignored .env* at the worktree root). `env set`
holds values in the control plane that the service's boxes get, dev boxes
and shared instances alike, in every `dev` run, `exec` and `ssh` shell. A
workbench gets every value its repo's services agree on. `env set` (admins
only) changes what every box of the service gets, shared instances and the
repo's workbenches included, from their next dev run or shell on, and marks
the repo's snapshot stale: ask the human first. A value only your box needs,
that no `env set` value names, goes in a gitignored file you `env push`,
then `sync <box> --restart`; most loaders let the process env win over a
file. `exec` and `ssh` do not see variables the dev script sets itself:
find the server's pid (ss -ltnp 'sport = :<port>') and check one name with
tr '\0' '\n' < /proc/<pid>/environ | grep -c '^NAME='; never dump it.
`env ls` also shows required names still unset. Names that make a shell,
loader, interpreter or package manager run code (PATH, NODE_OPTIONS, LD_*,
GIT_*, npm_config_*, YARN_*, ...) are refused: the box never takes them
from the control plane. Set those in the manifest's run.dev instead, e.g.
dev = "NODE_OPTIONS=--max-old-space-size=4096 pnpm dev".
Keep secrets out of shell history and the process list: a bare KEY reads its
value from stdin, and --from-file takes KEY=VALUE lines (blank lines, #
comments, and a leading export are skipped; a value wrapped in matching
quotes loses them; nothing else is interpreted).
tesser env set api STRIPE_KEY < ~/.stripe-key
tesser env set api --from-file .env.production
tesser env push
Usage: tesser env push [options] <box_id> [file...]
send gitignored .env* files to a box (every one at the worktree root, or the
files named)
Options:
--yes the user asked for this on a box you did not make
-h, --help display help for command
tesser env set
Usage: tesser env set <service> [KEY=VALUE|KEY...] [--from-file <path>]
set values for a service's shared instances
Arguments:
service
KEY=VALUE a bare KEY reads its value from stdin
Options:
--from-file <path> KEY=VALUE lines (- for stdin); a value in matching quotes
loses them, nothing else is interpreted
-h, --help display help for command
tesser env unset
Usage: tesser env unset [options] <service> <KEY...>
drop values
Options:
-h, --help display help for command
tesser env ls
Usage: tesser env ls [options] <service>
the names set, and required names still unset
Options:
-h, --help display help for command
tesser exec
Usage: tesser exec [options] [box_id] -- <cmd...>
sync the worktree and run a command on a box (the worktree's workbench when no
box is named)
Options:
--in <service> run in the service's root directory
--deps-of <service> give the box the service's dependency ports for the
duration
--force sync even if it would delete most of the files on the box
--yes the user asked for this on a box you did not make
-h, --help display help for command
Runs on the worktree's workbench when no box is named, creating one the
first time. The workbench never runs a dev server; tests, typechecks,
installs and builds belong there. Syncs the worktree first. The remote exit
code is yours. The box stays awake while this runs, so a job longer than your
tool timeout goes in a background task on your side, not nohup on the box.
--deps-of <service> gives the box that service's dependency ports for one
run. Values held by `tesser env set` are in the environment: a service box
gets its service's, a workbench gets every value its repo's services agree
on (a key two of them set differently is left out).
The command sees the same TESSER_* a dev run does:
TESSER_BOX_ID box_<hex>
TESSER_BOX_HOST box-<hex>.localhost, how the box and its peers reach it
TESSER_BOX_URL http://box-<hex>.localhost:<port>, on a service box this
laptop started (the manifest's first port)
TESSER_SLOT which boxes share backing state: `pinned` on a shared
instance, the worktree's cohort on a box this laptop started;
always lowercase [a-z0-9_-], at most 63
tesser dev
Usage: tesser dev [options] [service|box_id]
start a service's dev server from the current worktree
Options:
--force sync even if it would delete most of the files on
the box
--detach return once the run starts; `tesser wait <box>` then
waits for the port
--sleep-after <duration> the box sleeps after this long idle (30m, 4h), over
your sleep-after
--snapshot <snapshot_id> start a new box from this snapshot of the repo
instead of its current one
--no-snapshot start a new box blank instead of from the repo's
current snapshot
--yes the user asked for this on a box you did not make
-h, --help display help for command
Runs the manifest's setup, then dev, and waits for the primary port. Reuses
the box for (worktree, service). Running it again restarts the server when
it is not running or crashed under a file watcher (how you recover a
crash), or when the manifest, the files setup reads (lockfiles, package.json,
env files) or the env changed; other edits are the dev server's to
hot-reload. `tesser sync <box> --restart` always restarts. Each simultaneous
setup of the same service needs its own worktree.
Blocks until the primary port is healthy; wait for it to exit, never poll.
With --detach it returns once the run starts; `tesser wait <box>` then
blocks the same way.
Exits 1 with the log tail if the run dies before the port listens, its app
crashes under a file watcher (nodemon, nest --watch, node --watch, tsx
watch), or another process holds the port. Usually a missing env var (tesser
env --help) or a port that drifted because the dev server found its port
taken. While waiting it prints the log's last line every 30 seconds; raise
[health] timeout only if that line is still progress. A new box takes about
90 seconds to launch and setup can take many minutes more; do not `rm` a
box that only looks hung.
Waits on the box's own port, never its deps'. A box started before the infra
it needs lands against a dead port, and a client that started while nothing
was behind its dep can keep a dead connection (redis loops on EPIPE instead
of reconnecting). Once the dep is up, or after `wire`:
tesser sync <box_id> --restart.
Requests to port P reach the box from 127.0.0.1 with Host: localhost:P, and
a page's Origin arrives as http://localhost:<its port>, whether the browser
used localhost or the box address. So the app's base, auth and CSRF URLs
stay http://localhost:P. A URL the server renders for the browser to fetch
from another origin (an asset or CDN host, a websocket or HMR host, a static
URL prefix) names the box instead: http://$TESSER_BOX_HOST:P. A page on the
box address that calls localhost:<another port> reaches its own box without
its cookies. Per-IP throttles see every request as 127.0.0.1.
Deps resolve to a wire, else the org's shared instance of that service, else
nothing: `dev` names the port as it starts, every connection to it is
reset, and the box's log says so. Nothing is ever wired for you, and
starting a second service's box never rewires anything (tesser wire
--help). A manifest edit does not hot-register; re-run `dev` after
changing one.
The box runs the manifest it was synced, never a command from anywhere
else; a one-off command is tesser exec. Manifests: tesser service --help.
tesser wait
Usage: tesser wait [options] [box_id|service]
block until a box's dev server is healthy, or exit non-zero with why it never
will be
Options:
--timeout <duration> how long to wait (90s, 10m); default the manifest's
[health] timeout
-h, --help display help for command
Waits on a dev run already started (by `dev --detach`, `sync --restart
--detach`, or a `dev` that timed out) the way `dev` does, wired deps
included: exit 0 once the primary port is healthy, else exit 1 with the
reason and the log tail when setup failed, the dev command exited, its app
crashed under a file watcher, another process holds the port, or the timeout
ran out. It prints where the run is every 30 seconds, including a health
check that keeps answering the same 5xx, and warns when setup's last line has
not changed for 5 minutes. With no argument, the worktree's one dev box; a
service name means this worktree's box for it.
tesser logs
Usage: tesser logs [options] [box_id]
the dev server's output; with no id, the current worktree's box
Options:
-n, --lines <n> how many lines (default: 200)
--grep <regex> only lines matching this extended regex, earlier runs
included
--health keep the [health] probe's own request lines
-f, --follow keep following
-h, --help display help for command
The current run's last lines, without GET requests for the [health] path,
which are the probe's (--health keeps them). Each
`dev` or restart starts a new log, and so does a run past 10 MB:
~/.tesser/dev.log is the newest, dev.log.1 and dev.log.2 the ones before.
--grep searches all three, oldest first, prefixes the older ones' lines
with their file name, and exits 1 when nothing matches.
tesser logs <box_id> --grep 'error|warn' -n 50
tesser sleep
Usage: tesser sleep [options] <box_id>
power a box down; any command targeting it wakes it
Options:
--yes the user asked for this on a box you did not make
-h, --help display help for command
Idle boxes sleep on their own: workbenches after 10 minutes, instance boxes
after 2 hours (`tesser sleep-after` changes yours). A box asleep for 16 hours is removed. Disk and
id persist through sleep; any command targeting the box wakes it, about a
minute. A running dev server does not count as activity; proxied traffic
does. Neither does a job left running on the box with nohup, setsid, or
tmux: run it as `tesser exec` in the background on your side, and the box
stays awake until that command exits.
tesser wake
Usage: tesser wake [options] <box_id>
power a box up and wait until it answers
Options:
-h, --help display help for command
tesser util
Usage: tesser util [options] <box_id>
a box's cpu (% of all vcpus) and memory over time, one row per step, kept 7 days
Options:
--since <duration> how far back, like 30m, 12h or 7d (default: 3600)
--json
-h, --help display help for command
tesser sleep-after
Usage: tesser sleep-after [options] [duration]
how long your instance boxes sit idle before they sleep; bare form shows it
Arguments:
duration 30m, 4h; 5m to 24h
Options:
--box <box_id> set one box's clock instead, over its owner's
--default back to the default: the org's for you, the owner's for a box
--yes the user asked for this on a box you did not make
-h, --help display help for command
Your own idle clock, per org: every instance box you own sleeps this long
after its last activity instead of the 2 hour default. Workbenches keep
their 10 minutes. Takes effect on your existing boxes immediately, so a
box already idle longer than the new value sleeps now.
`--box <box_id>` (or `tesser dev --sleep-after`) sets one box's clock, any
class, over its owner's. A pool claim starts a box with none.
tesser keep
Usage: tesser keep [options] <box_id>
never let a box sleep or expire on its own; only when the user asks, never for a
long job
Options:
--off back to the idle clock
--yes the user asked for this box to stay up, or for this on a box you
did not make
-h, --help display help for command
Only when the user asks for it. A kept box bills every second it is awake,
until someone turns it off. For a long job, run `tesser exec` as a
background task on your side; for more idle time, `tesser sleep-after`.
An agent is refused without --yes.
A kept box is exempt from the idle clock: it never sleeps on its own and is
never removed for being asleep too long, like a database the rest of the
org depends on.
`keep` wakes the box if it is asleep. `sleep` and `rm` still act
immediately; a kept box put to sleep stays asleep until something targets it.
`keep --off` returns it to the idle clock.
tesser ssh
Usage: tesser ssh <box_id|service> ['<command line>' | -- <cmd...>]
an interactive shell in ~/workspace, or one command there (no sync first); a
service name means its org default box
Options:
-h, --help display help for command
For looking, never editing: the next sync overwrites the box. A quoted
command line runs in the box's shell, as with ssh: tesser ssh <box_id>
'git status'; after --, the words are passed exactly. A service
name instead of a box id lands on that service's org default, the shared
instance any member can run scripts against:
tesser ssh api -- bun run scripts/backfill.ts. Everything after the box
belongs to the command, flags included. A command line sees the TESSER_*
listed in `tesser exec --help`; the interactive shell gets none of them.
From a terminal, a command line gets a terminal on the box too (ssh -tt).
One command per ssh;
chained commands often come back empty over Session Manager. If ssh asks
for an AWS profile, the org runs its boxes in its own AWS account and no
profile is set: an admin sets the org's default with
tesser cloud connect --aws-profile, or this laptop names its own with
tesser cloud aws-profile.
tesser rm
Usage: tesser rm [options] <box_id...>
remove boxes and their disks; wires that pointed at them fail loud until
re-wired
Options:
--yes the user asked for this on a box you did not make
-h, --help display help for command
tesser share
Usage: tesser share [options] <box_id>
a review link for a box and everything it depends on; anyone in the org opens it
with tesser review
Options:
--ttl <duration> how long the link works (12h, 7d); default 7d
--revoke end every review link for the box
--yes the user asked for this on a box you did not make
-h, --help display help for command
tesser review
Usage: tesser review [options] <link>
open a review link: the box and its deps get addresses on this laptop
Arguments:
link the https://tesser.sh/r#... link, or its token
Options:
-h, --help display help for command
tesser wire
Usage: tesser wire <box_id> [<service> <target_box_id|--shared>]
point a box's <service> dependency at a box, or back to the org's shared
instance; bare form shows every dep
Options:
--shared back to the org's shared instance
--yes the user asked for this on a box you did not make
-h, --help display help for command
How deps resolve
A manifest's [deps] maps loopback ports on the box to other services, so
the app keeps its localhost:… config. Each dep port reaches, in order: the
box it is wired to, else the org's shared instance of that service, else
nothing: `dev` and `make` name the port, every connection to it is
reset, and the box's log says so. Nothing is ever wired for you. A
single-service change needs no wiring: `tesser dev web` against the
shared api just works.
Two dev boxes that talk to each other
API=$(tesser dev api) in the backend worktree
WEB=$(tesser dev web) in the frontend worktree
tesser wire "$WEB" api "$API" the human opens the address web's dev printed
tesser sync "$WEB" --restart if web started before the wire
tesser wire "$WEB" api --shared done: back to the shared api
When the frontend lives in a repo you are not editing, make a worktree of
it and `dev` from there: git -C ../frontend worktree add /tmp/web-<branch>
origin/main. `dev` reuses the box for (worktree, service), so each
simultaneous setup needs its own worktree.
`wire` returns once this laptop's daemon routes the change, and refuses
a target that is not a box of that service. Bare `tesser wire <box_id>`
shows where every dep points. `tesser rm` leaves the wires that pointed
at the box in place; a wire whose target is gone fails loud, so re-wire it
or return it to --shared. The org's shared instances never point at
anyone's dev box.
Browser-testing a backend change
A backend box alone is not a browser test. Run a frontend box of your own
from a worktree of the frontend repo, wire it to your backend box, leave
unchanged deps on their shared instances, and return the frontend's URL
with the wiring. One frontend cannot show two people different backends.
Unit tests and builds alone never need a frontend.
How a box addresses another box
Two ways, for different questions. A wired dep port is 127.0.0.1:<dep port>
on the box and answers whatever Host header is sent: use it when the app's
config names a fixed port and you want to swap what sits behind it.
http://box-<id>.localhost:<port> works from a box too: every box gets a
door for each peer in the org, so one box can name another directly. Use
it when a single box has to reach many targets, which a dep port cannot
express; one dep is one target. The run command, an exec, and an ssh
command line see their own box as TESSER_BOX_ID, TESSER_BOX_HOST
(box-<hex>.localhost) and TESSER_BOX_URL (first declared port), so a dev
box can hand its address to a shared service, for webhooks say. They get
TESSER_SLOT: which boxes share backing state (queue names, a redis db).
Every shared instance is `pinned`; a dev box is its worktree's folder plus
its owner, so a worktree's cohort shares one slot and nobody else's does,
and a branch switch moves nothing. It is always lowercase [a-z0-9_-], at
most 63 characters. Key shared-infra names on it, never on the
checkout's branch or sha.
The laptop's proxy serves only boxes this laptop started. A shared
instance's box-<id>.localhost answers 404 (unknown box) from the laptop;
reach those from a box. If box-<id>.localhost resolves to ::1 from a box,
that box's peer doors never installed: `grep box_ /etc/hosts` there
should list every peer in the org, and `journalctl -u tesser-boxd` says
why not. Both boxes need a current agent: `tesser status`, then
`tesser boxd update`.
tesser service
Usage: tesser service [options] [command]
the org's service registrations
Options:
-h, --help display help for command
Commands:
ls|list [options] each service's shared instances; worktree manifests the org
has never seen show as unregistered
rm <name> forget a service: its shared instances and env values
A service is a TOML file at .claude/skills/devboxes/<service>.toml. The file
name is the service name, and names are org-global. Every .toml in that
directory is read as a manifest. .claude/skills/tesser, .agents/skills/devboxes
and .agents/skills/tesser are read too; manifests in two of them is an error. A manifest carries facts only; secret
values live in the control plane (`tesser env set`), never in the file.
root = "apps/web" optional: the service's directory, relative to the repo root
ports = [3000] required; several allowed; first = primary
size = "standard" optional default for make/dev: small|standard|large|xlarge
box_address = true optional: a page opened on bare localhost moves to box-<id>.localhost
[run] required, both keys
setup = "pnpm install" idempotent environment recipe, runs before dev
dev = "pnpm dev" the server; must listen on the primary port
[health] optional
path = "/healthz" probed on the primary port
timeout = "90s" how long dev waits for the port ("500ms", "90s", "2m")
[deps] optional
5001 = "backend" localhost:5001 on this box reaches backend's primary port
9091 = "search:9090" a specific port of a dependency
[env] optional
files = [".env.local"] gitignored files every sync ships, relative to root
required = ["DATABASE_URL"] names `tesser env set <service> KEY=VALUE` must hold
Rules
Own ports and dep ports share the box's loopback, so a dep's local port
cannot be one of the service's own ports. Declared ports may bind
127.0.0.1 or 0.0.0.0; either works, and an all-interfaces bind is not
public. setup and dev each run as an sh script; dev starts only once
setup exits 0. A manifest edit does not hot-register; re-run `dev`
after changing one. setup also runs on the snapshot builder, whose disk
the repo's new boxes start from (unless --no-snapshot), and sees no
TESSER_BOX_*: anything specific to one box (its address, its id, a
per-box secret) belongs in dev, never in setup.
`service ls` prints one line per service: ports, the org's default box (-
when none), and each shared instance as state sha power. Manifests in this worktree the
org has never seen show as unregistered. Run it before `dev` when a dep
might have nothing behind it. `service rm <name>` unregisters a service and
removes its shared instances and env; dev boxes stay.
tesser service ls
Usage: tesser service ls|list [options]
each service's shared instances; worktree manifests the org has never seen show
as unregistered
Options:
--json
-h, --help display help for command
tesser service rm
Usage: tesser service rm [options] <name>
forget a service: its shared instances and env values
Options:
-h, --help display help for command
tesser nuke
Usage: tesser nuke [options]
remove every box in the org, plus every service registration and shared
instance; env values survive
Options:
--force skip the confirmation
-h, --help display help for command