> ## 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.

# CLI reference

> Every command, exactly as `tesser <command> --help` prints it

The binary is the source of truth. This page is `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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser version [options]

print the CLI version

Options:
  -h, --help  display help for command
```

## tesser licenses

```text theme={"theme":"css-variables"}
Usage: tesser licenses [options]

show bundled rsync's license and extract its complete source

Options:
  -h, --help  display help for command
```

## tesser login

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser logout [options]

revoke the saved token and forget it

Options:
  -h, --help  display help for command
```

## tesser whoami

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser org use [options] <org_id>

make one of them the default

Options:
  -h, --help  display help for command
```

## tesser member

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser member ls|list [options]

list members

Options:
  --json
  -h, --help  display help for command
```

### tesser member add

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser member token rm|revoke [options] <membership_id> <token_id>

revoke one token

Options:
  -h, --help  display help for command
```

## tesser grant

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser grant ls|list [options]

list the org's grants

Options:
  --json
  -h, --help  display help for command
```

### tesser grant rm

```text theme={"theme":"css-variables"}
Usage: tesser grant rm|revoke [options] <grant_id>

revoke a grant; no more exchanges

Options:
  -h, --help  display help for command
```

## tesser cloud

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser pool ls [options]

list unclaimed pool boxes

Options:
  --json
  -h, --help  display help for command
```

### tesser pool drain

```text theme={"theme":"css-variables"}
Usage: tesser pool drain [options]

remove every unclaimed pool box

Options:
  -h, --help  display help for command
```

## tesser snapshot

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser snapshot show [options] <snapshot_id>

a snapshot

Options:
  --json
  -h, --help  display help for command
```

### tesser snapshot rm

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser top [options]

the org's boxes and wiring, live, in a terminal UI

Options:
  -h, --help  display help for command
```

## tesser status

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser env unset [options] <service> <KEY...>

drop values

Options:
  -h, --help  display help for command
```

### tesser env ls

```text theme={"theme":"css-variables"}
Usage: tesser env ls [options] <service>

the names set, and required names still unset

Options:
  -h, --help  display help for command
```

## tesser exec

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser wake [options] <box_id>

power a box up and wait until it answers

Options:
  -h, --help  display help for command
```

## tesser util

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
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

```text theme={"theme":"css-variables"}
Usage: tesser service rm [options] <name>

forget a service: its shared instances and env values

Options:
  -h, --help  display help for command
```

## tesser nuke

```text theme={"theme":"css-variables"}
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
```


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