Skip to content
Kortix
Esc
↑↓navigate↵open⌘Jpreview
On this page

Sandboxes & previews

The cloud computer behind each session: providers, image and hardware, environment, ports and previews, files, and troubleshooting.

A sandbox is the isolated cloud computer a session runs on. Each session gets its own sandbox, with the project repository cloned at /workspace on the session’s branch. This page is for people who customize that computer, open the apps an agent runs in it, find its files, and debug it. Starting, stopping and sleep rules are on Sessions.

Describe the computer

Add Dockerfile.dev to the repository. Start from a Debian or Ubuntu image and install what your agents need.

FROM ubuntu:24.04
RUN apt-get update \
    && apt-get install -y --no-install-recommends postgresql-client \
    && rm -rf /var/lib/apt/lists/*

Declare the template

Name it in kortix.yaml and make it the default. kortix sandboxes add dev --dockerfile Dockerfile.dev --cpu 4 --memory 8 writes the template entry for you. Add default yourself.

sandbox:
  templates:
    - slug: dev
      dockerfile: Dockerfile.dev
      cpu: 4
      memory: 8
  default: dev

Check it, then merge

kortix sandboxes build --local builds the image on your own Docker before you push. Kortix reads the Dockerfile from the default branch, so merge the change. The next new session builds the image. kortix sandboxes health shows when it is ready.

Open what the agent runs

When the agent starts a dev server on port 3000, run kortix sessions forward <session_id> --port 3000 and open the local address it prints.

Inside the sandbox

Path or port What it is
/workspace The project repository, checked out on the session branch. The working directory.
/workspace/incoming Files that kortix sessions new --with-file uploads before the first prompt.
/drives Shared folders, when the Files feature is on. The person’s own folder is /drives/me. See Files.
/home/kortix Home of the kortix user. The agent runs as kortix, with passwordless sudo.
Port 8000 The Kortix daemon. It runs the agent harness and proxies every other port.
  • The session branch is named after the session_id. Commits push to that branch through the Kortix git proxy. By default, work reaches the base branch through a change request.
  • The agents, skills and tools a session runs come from a read-only copy of the base branch, not from /workspace. An edit in /workspace takes effect after it reaches the base branch. See Config comes from the base branch.
  • An agent with workspace: { project_repository: false } gets no clone and no git variables. In kortix_version: 3 that is the default: an agent opts in with project_repository: true. See Workspace.
  • The sandbox has its own id at the provider, the external id. It is not the session_id. Previews and the API proxy use the external id. kortix sessions info <session_id> --json shows it in sandbox_url, after /v1/p/.

Ports and previews

Any server that listens on a port in the sandbox is reachable from outside it. Port 8000 is the Kortix daemon. Kortix gives each port two addresses.

Form Address Use it for
Preview origin https://{env}-p{port}-{label}.p.kortix.com on Kortix Cloud. {label} is the external id in lowercase, with _ replaced by -. A browser.
Path {api}/v1/p/{external_id}/{port}/ Scripts and API clients.

The preview origin serves the app at /, on its own origin. Root-absolute links, cookies, service workers, hot reload and WebSockets work with no change to the app. Sign-in is a cookie for that origin: a cold visit asks you to sign in to Kortix, then returns you to the app. The proxy removes X-Frame-Options and frame-ancestors, so the session page can show the app in a frame. GET /v1/p/config returns the address template for the instance you use.

  • Open a preview: the session page’s preview panel offers ports 3000 (App preview), 5173 (Frontend preview), 8080 (Dev server) and 8001 (API docs), plus any other port.
  • Get a link from a terminal: kortix sessions preview <session_id> [port] prints a URL for the port (default 3000). The URL carries your sign-in token, so do not share it. --list prints the preview candidates.
  • Forward to your machine: kortix sessions forward <session_id> --port 3000 serves the port on localhost:3000, or on the next free port when 3000 is in use. It prints the address and runs until you press Ctrl+C. --port 3000:4000 picks the local port, and --port repeats. It forwards HTTP and WebSockets. The sandbox must be running.
  • From code: kortix.session(projectId, sessionId).previewUrl(port, path) returns the browser address. See Sessions from code.
  • Share with someone outside Kortix: create a public link. See Public links.

A preview request to a stopped sandbox wakes it. Preview traffic from a signed-in person also keeps the sandbox awake: see When a session sleeps.

To run a server that outlives the agent’s tool call, start it in tmux.

Files

A session’s files live in four places. Pick the store by what you need.

Store What it holds Read and write it
Live workspace /workspace in the running sandbox, with uncommitted work and build output. kortix sessions files <session_id> ls, status, find, write, touch, mkdir, mv, rm. kortix sessions cp <session_id>:<path> <dst> copies files, -r for a directory. Both wake a stopped sandbox.
Committed repository What a branch holds in git. kortix files ls, cat, search, history, diff, download, with --ref <branch>. The project’s Files page, not Customize → Files. No sandbox needed.
Session attachments Files people attached to the session, and copies of files the agent showed. Saved at the end of every turn. kortix sessions attachments <session_id>, with --download <attachment_id> or --all, and --out <dir>. Works while the session is stopped.
Shared folders Folders for the whole project, kept in sync with sessions. Customize → Files. A new session mounts them under /drives.

kortix sessions cp also copies between two sandboxes: kortix sessions cp <session_a>:/workspace/out <session_b>:/workspace/in -r. Paths in kortix sessions files resolve under /workspace unless they start with /workspace, /tmp, /home or /opt.

Shared folders

Every person has a private folder, and any folder can be shared with people, groups and agents. A new session mounts:

  • the folders the agent or the whole project has a grant on, at /drives/<folder name>;
  • in a private session that the person started, also that person’s own folder at /drives/me and every folder shared with them or their groups.

Shared folders need the Files feature. It needs Platinum and the project’s Volumes flag (Customize → Settings → Feature flags). With Files on, a session on another provider does not start. A platform admin can turn on drive sync: the sandbox then copies each folder into the same /drives path and keeps it in sync through Kortix.

The image and templates

A sandbox image has two layers: your Dockerfile or image, and the Kortix runtime layer on top. A project with no template uses the platform default image: ubuntu:24.04 plus the runtime layer.

Declare a template

Templates live under sandbox.templates in kortix.yaml. You can also create one in Customize → Settings → Sandbox templates. slug, name, dockerfile or image, entrypoint, cpu, memory, disk and container_runtime are the fields. sandbox.default names the template that sessions use. Full rules and the template order are in the manifest reference.

What the runtime layer adds

  • System packages: git, curl, sudo, tmux, build-essential, ffmpeg, fonts.
  • Shell tools: rg, fd, bat, jq, fzf, tree, htop, lsof, rsync, sqlite3, wget, zip, unzip, zstd, git-lfs, ssh, nc, nano.
  • Document tools: LibreOffice, Pandoc, Poppler, qpdf, Tesseract OCR, LaTeX.
  • Node.js and npm, managed by pnpm. Python, managed by uv, as python and python3. Install Python packages per command with uv run --with <package>.
  • bun, opencode, and agent-browser with a built-in Chromium.
  • The kortix CLI and the Kortix daemon, which starts as the entrypoint.
  • /etc/profile.d/zz-kortix.sh, which puts these tools on PATH in every terminal shell. It keeps every PATH entry your Dockerfile adds.

Dockerfile rules

Rule Why
Start FROM a Debian or Ubuntu image. The runtime layer installs with apt-get. Its packages resolve on Ubuntu 22.04, Ubuntu 24.04 and Debian 12.
Do not set ENTRYPOINT or CMD. Kortix replaces both to start its daemon.
Do not use port 8000. The daemon listens there.
Do not COPY or ADD files from the repository. The build context is empty. Fetch files with RUN, or read them from /workspace at runtime.
Do not put credentials in the image. Store them as secrets. Kortix delivers them when the session starts.

Builds

Kortix names each build by a hash of the Dockerfile bytes (or the image reference), the hardware, container_runtime, and the Kortix runtime version. An unchanged hash reuses the existing image. A changed hash builds a new image when the next session needs it, and later sessions reuse it. A Dockerfile edit inside a session takes effect after it merges to the default branch.

Command What it does
kortix sandboxes ls Lists templates and their state at the provider.
kortix sandboxes health Shows if the default template is ready.
kortix sandboxes builds Shows the last 25 builds.
kortix sandboxes build <slug> Starts a build.
kortix sandboxes rebuild <slug> Deletes the existing image, then builds again.
kortix sandboxes build --local [slug] Builds on your own Docker with the same empty context. Needs no sign-in. --print prints the composed Dockerfile. --no-layer builds only your Dockerfile.
kortix sandboxes fix Starts a session that has the last failed build log, so an agent can repair the Dockerfile.
kortix sandboxes add, update, rm Edit sandbox.templates in the local kortix.yaml.

kortix validate also checks these Dockerfiles before you push.

Hardware and Docker

Field Default Range
cpu 2 vCPU 1 to 32
memory 4 GiB 1 to 128 GiB
disk 20 GiB 1 to 500 GiB

A value above the range warns, and Kortix uses the maximum. A value below the range is an error in kortix validate, kortix ship and the change request merge. Kortix has no GPU sandboxes: a gpu key gets a warning. The hardware is part of the image, so a change applies to the next session. A running session keeps its size.

Docker in the sandbox

Set container_runtime: true on a template to run Docker inside its sandboxes. docker compose and supabase start then work as they do on your own machine.

sandbox:
  templates:
    - slug: dev
      dockerfile: Dockerfile.dev
      container_runtime: true

Install Docker in your Dockerfile, for example RUN curl -fsSL https://get.docker.com | sh.

The runtime layer adds the kortix user to the docker group and starts dockerd at boot. Its log is /var/log/dockerd.log. If dockerd stops, start it again with sudo sh -c 'nohup dockerd >/var/log/dockerd.log 2>&1 &'.

On Platinum, container_runtime also adds the kernel modules Docker needs for its networks and storage.

Environment variables

Kortix sets these variables in every session sandbox.

Variable Value
KORTIX_PROJECT_ID The project id.
KORTIX_SESSION_ID The session_id.
KORTIX_BRANCH_NAME The session branch. Equal to KORTIX_SESSION_ID.
KORTIX_BASE_REF The branch the session started from.
KORTIX_DEFAULT_BRANCH Equal to KORTIX_BASE_REF. It differs from the project’s default branch when the session started from another branch.
KORTIX_BASE_SHA The base commit. Set on a new session’s first boot only.
KORTIX_REPO_URL The clone URL, through the Kortix git proxy.
KORTIX_API_URL The Kortix API base, ending in /v1.
KORTIX_FRONTEND_URL The Kortix web app base. Use it for links a person opens.
KORTIX_SERVICE_PORT 8000.
KORTIX_AGENT_NAME The session’s agent.
KORTIX_MODEL The session’s model, when one is set.
KORTIX_HARNESS pi on a pi session. Not set on an OpenCode session.
KORTIX_LLM_BASE_URL The LLM gateway.
KORTIX_TOKEN The session credential. See below.
KORTIX_PROJECT_SECRET_NAMES Comma-separated names of the secrets delivered to this session.

KORTIX_REPO_URL, KORTIX_BRANCH_NAME, KORTIX_BASE_REF, KORTIX_DEFAULT_BRANCH and KORTIX_BASE_SHA are absent when the agent has no repository access.

KORTIX_TOKEN is the one Kortix credential in the sandbox. It names the project, the session and its agent. A session whose agent is declared in kortix.yaml acts as that agent’s service account, with its kortix_permissions capped by its ceiling role. The person who started the session decides only which personal resources reach a private session. See What an agent may do. The kortix CLI, git, the LLM gateway and connector calls all use it, and each API route still checks its own permission. Inside a sandbox the CLI needs no sign-in: see Inside a session sandbox.

Secrets. A secret with environment exposure arrives as a plain variable. An egress-enforced secret arrives as a handle, not the value. A secret with exposure none never enters the sandbox. The agent’s grant decides which secrets a session gets: see Secrets. Kortix drops a project secret named KORTIX_*, OPENCODE_*, or a system name such as PATH, HOME or PORT.

What never enters the sandbox: the upstream git token (pushes go through the Kortix git proxy) and connector credentials.

Sandbox providers

Platinum is the reference sandbox provider. New sessions run on Platinum by default. The operator of the Kortix instance decides which providers are on.

Provider Id Docker in the sandbox Persistent machines and shared folders US region
Platinum platinum Yes Yes Yes, with the US Region flag
Daytona (legacy) daytona Yes No No

A new session gets its provider in this order:

  1. The provider field on the create request (POST /v1/projects/{projectId}/sessions). A provider that is not on returns 400.
  2. The project’s provider pin, when that provider is still on.
  3. The instance’s distribution across its enabled providers.

Pin a provider for a project

  1. Open Customize → Settings → Sandbox templates.
  2. Under Routing, pick a provider, or the automatic choice to remove the pin.

From a terminal, run kortix sandboxes provider <name>. kortix sandboxes provider --clear removes the pin. kortix sandboxes provider status shows the latest switch.

  • A pin needs the project.settings.write permission. Only a person can set it. A session token gets 403 with code agent_session_forbidden. A session that needs another provider passes provider on create instead.
  • A switch to a different provider prepares the project’s images on the target, verifies them, then activates the pin. New sessions use the old provider until the switch completes. The CLI follows the switch for up to 600 seconds (--timeout <sec>).
  • The US Region flag (Customize → Settings → Feature flags) places the project’s new Platinum sandboxes in the US region. It changes where compute runs, not where the API, database or archives live. Existing sandboxes keep their region. After a new sandbox image, the first session can wait while Platinum copies the image to the region. If the copy fails, the session starts in the home region instead. That sandbox keeps the home region on restart. A replacement sandbox asks for the US region again. The flag shows only when the operator configured a US region.

Troubleshooting

Open a terminal in the sandbox with kortix sessions shell <session_id>. It reattaches to the existing terminal. --new starts another one. kortix sessions shell <session_id> ls lists terminals, and kill <pty-id> ends one.

The daemon answers three diagnostic routes through the API proxy. Call them with a personal access token (API keys and tokens) as a person who can open the session:

curl -H "Authorization: Bearer kortix_pat_..." \
  "https://api.kortix.com/v1/p/<external_id>/8000/kortix/logs?source=all&tail=1000"

Replace logs?source=all&tail=1000 with health or diag for the other two routes. On a self-hosted instance, use its API host.

Route Returns
GET /kortix/health JSON: status (ok, error, or the harness state), boot_error, harness.id (opencode or pi), and capabilities.
GET /kortix/logs Plain text. source is daemon (default), opencode on an OpenCode session, or all. tail is 500 lines by default, 5000 at most.
GET /kortix/diag One JSON report: harness state, boot timeline, memory, disk and load, and the tail of the logs. tail is 200 by default, 2000 at most. It holds no secrets.
Symptom What to do
The header shows Config failed to load. The new agent config failed. The session runs the last working release, or the platform default config. Fix the config on the base branch. See Config comes from the base branch.
The session runs old agents or skills. Merge the change to the base branch, then run kortix sessions reload <session_id>.
The image build failed. Read kortix sandboxes builds. Reproduce it with kortix sandboxes build --local, or run kortix sandboxes fix.
A preview shows nothing. Open kortix sessions shell <session_id> and check that a server listens on that port, for example with lsof -iTCP -sTCP:LISTEN. Start long-running servers in tmux.
A turn stopped with a memory message. The sandbox reached 92% of its memory. Kortix first stops the largest process that is not the agent runtime, up to 2 processes. If memory stays at 92%, it ends the turn. Raise memory on the template (see Hardware and Docker), or run fewer heavy processes at once.
docker cannot reach the daemon. Set container_runtime: true on the template, install Docker in the Dockerfile, and read /var/log/dockerd.log.
400 Unknown or disabled sandbox provider on create. The provider value is not on for this instance. Use kortix sandboxes provider to see the enabled providers.

Was this page helpful?