Skip to main content

Work on a GitHub repository in a sandbox

This guide clones a GitHub repository into a sandbox, works on it with git, and opens a pull request. It also connects SSH or Visual Studio Code to the sandbox and runs Claude Code on the repository.

You need:

  • tritonctl signed in to your cloud.
  • The egress_domains feature gate, which your operator turns on. --repo opens egress to GitHub by name.
  • A NAT gateway and a default route in your VPC, for egress.
  • A GitHub token from gh auth token, or in a local environment variable.

Use a fine-grained GitHub token for the one repository, with only contents and pull request write access.

Where the GitHub token goes​

tritonctl never takes the token as a flag value. It reads it from gh auth token, or from the local variable you name with --github-token-env <VAR>.

The token goes into the guest only in the environment of one git exec that moves objects: clone, fetch, push, or ls-remote. Those execs run with git hooks, the fsmonitor, and custom SSH commands turned off. git reads the token through a credential helper set for https://github.com only. The token is not in the command line, the remote URL, a guest file, or the sandbox's labels and metadata, and the control plane does not store an exec's environment.

While that exec runs, another process of the same guest user can read its environment. The token's scope is your limit.

Clone and run​

tritonctl sandbox create --name app --repo owner/app --branch main
tritonctl sandbox exec app --cwd /work/app -- make test

--repo clones into /work/<NAME> once the sandbox runs. The clone runs as the sandbox's default user: sandbox for a built-in template, or for your own template the user its build recorded, else root. It also adds the github network preset: github.com, *.github.com, *.githubusercontent.com, and codeload.github.com. Add other names your build needs with --allow-out-domain, for example pypi.org. --net github adds the same preset without a clone.

Commit, push, and open a pull request​

tritonctl sandbox git app -- config user.name "Your Name"
tritonctl sandbox git app -- config user.email you@example.com
tritonctl sandbox git app -- switch -c fix-typo
tritonctl sandbox git app -- commit -am "Fix a typo"
tritonctl sandbox pr app --title "Fix a typo" --draft

sandbox git runs in the only checkout under /work. Give --repo-dir when there is more than one. Put the git subcommand first. A pull gets no token, because a checkout can run a filter that the repository names. Run fetch, then merge.

sandbox pr pushes the current branch to origin and opens the pull request from your workstation, against the default branch or --base. It prints the pull request URL. The title defaults to the last commit's subject.

Connect with SSH or VS Code​

tritonctl sandbox ssh-config app --install
ssh app.sandbox.triton

ssh-config makes a key pair for this sandbox on your workstation, adds the public key to the guest's sandbox account, starts sshd on the guest's loopback address, and pins its host key. The entry's ProxyCommand is tritonctl sandbox port-forward --stdio, so SSH uses the same authenticated tunnel as any other port. The sandbox opens no SSH port.

--install writes ~/.ssh/tritonctl/app.sandbox.triton.conf and adds an Include line at the top of ~/.ssh/config. Without --install, the entry is printed.

In VS Code, run Remote-SSH: Connect to Host and pick app.sandbox.triton. The guest allows local port forwarding, which VS Code needs. It refuses passwords, root, and agent forwarding. scp works with the same host name.

Run Claude Code on the repository​

export ANTHROPIC_API_KEY=<ANTHROPIC_API_KEY>
tritonctl sandbox claude --repo owner/app

This uses a sandbox named claude-app, made on first use. The repository is cloned first, while the sandbox can reach GitHub and not the Anthropic API. GitHub is then closed, and claude starts in /work/app with access to the Anthropic API only. claude never gets the GitHub token, so a push from that sandbox is refused. Copy the work out with fs get, or push from a separate sandbox.

tritonctl sandbox claude also reads ANTHROPIC_AUTH_TOKEN or CLAUDE_CODE_OAUTH_TOKEN. ~. at the start of a line detaches and leaves claude running.

Make many copies of a prepared repository​

Build a template with the toolchain. A Dockerfile build needs the templates_from_dockerfile feature gate, which is off until your operator turns it on for your tenant. Without it, build from an OCI image with --image instead. This Dockerfile sets no USER, so commands in sandboxes made from it run as root.

Dockerfile
FROM rust:1
WORKDIR /work
tritonctl sandbox template build rust-dev --dockerfile Dockerfile --follow
tritonctl sandbox create --name app-warm --template rust-dev --repo owner/app
tritonctl sandbox exec app-warm --cwd /work/app -- cargo build
tritonctl sandbox snapshot create app-warm --name built

Fork copies on the same compute node, each with the clone and the build cache:

tritonctl sandbox fork app-warm --from-snapshot built --count 4 --name-prefix app

Or build a template from the snapshot, for new sandboxes on any node:

tritonctl sandbox template build app --from-snapshot app-warm/built --wait
tritonctl sandbox create --template app --net github

A copy made after ssh-config shares the guest's SSH host key. Take the snapshot before you run ssh-config.

If a step fails​

SymptomCauseFix
403 FeatureDisabled naming egress_domainsDomain egress is not on for your tenant.Ask your operator.
The create is refused for egressThe VPC has no NAT gateway or default route.Ask the VPC owner to add both.
gh auth token fails before the createNo GitHub CLI session.Run gh auth login, or pass --github-token-env.

See also​