# Web Terminal

Daytona provides a browser-based web terminal for your sandboxes. Run commands, view files, and debug from your browser without installing local tools.

## Use cases

The web terminal is used when a person needs a shell in a sandbox from the browser, with no local tools.

- **Command execution**: a person runs shell commands in the sandbox from the sandbox details page. The **Terminal** tab opens by default, so opening a sandbox lands in a shell.
- **File management**: a person moves through the file system and views and edits files. **Open terminal here** in the **Files** tab starts a shell in the selected folder.
- **Full-screen programs**: programs such as **`top`**, **`vim`**, and **`htop`** work as in a local terminal. Resizing the browser window resizes the terminal in the sandbox.
- **Debugging**: a person reads logs, checks processes, and finds the cause of a problem in a running sandbox.
- **Package management**: a person installs dependencies and configures the environment by hand before code or an agent uses the sandbox.
- **Several shells**: multiple terminal sessions run side by side in one sandbox. The browser remembers the tab order, the pinned tabs, and the active tab for each sandbox.
- **Shells shared with code**: each session is a PTY process, so the SDK, the CLI, or the API can attach to the same shell. The browser and the attached client share keystrokes and output.
- **Page reloads**: sessions stay alive while the sandbox runs. Reloading the page reconnects to the existing shells.

## Access from Dashboard

The web terminal is built into the sandbox details page of the [Daytona Dashboard ↗](https://app.daytona.com/dashboard/sandboxes).

1. Go to [Daytona Sandboxes ↗](https://app.daytona.com/dashboard/sandboxes)
2. Locate the running sandbox you want to access
3. Click **Open terminal** in the sandbox row, or the sandbox's **Terminal** tab

The **Terminal** tab is the default tab of the sandbox details page, so opening a sandbox lands you directly in a shell. The tab is also reachable via `?tab=terminal` in the sandbox details URL. The web terminal is available only for sandboxes in the running state. If your sandbox is stopped, start it before attempting to access the terminal.

### Multiple sessions

Each terminal tab is an interactive shell running as a [PTY process](https://www.daytona.io/docs/en/v2/pty.md) inside the sandbox. Opening the **Terminal** tab on a sandbox with no sessions creates the first one automatically. You can:

- Open additional sessions with the **+** button and switch between them
- Drag tabs to reorder them, or right-click a tab to close, close others, or pin it
- Close a session to stop its shell process

Pinned tabs stay fixed on the left of the tab strip, cannot be dragged, and are skipped by **Close others**. Tab order, pinned tabs, and the active tab are remembered in your browser per sandbox, so reopening the sandbox restores the same layout.

Sessions stay alive while the sandbox runs, so reloading the page reconnects to your existing shells. A shell that exits on its own, for example after `exit`, closes its tab within seconds.

### Open a terminal in a directory

From the **Files** tab, open the actions menu (**⋯**) of a folder and choose **Open terminal here** to start a new terminal session with that directory as its working directory.

## Shell

Each session starts an interactive shell (`-i`) with an initial size of 80x24 that is immediately resized to fit the browser viewport. The shell is the login shell of the sandbox user as listed in `/etc/passwd`, falling back to bash, zsh, then sh from the PATH.

Full-screen programs such as top, vim, or htop work as in a local terminal. Resizing the browser window or the side panel resizes the remote PTY.

## Sessions and scrollback

Web terminal sessions are regular PTY processes on the sandbox, named with a web-term prefix and a number that sets the tab title. Only web-term processes appear as tabs; the web terminal neither shows nor touches PTY sessions started through the SDK or API.

Sessions are ordinary processes, so you can list and attach to them programmatically. SDK and browser clients attached at once share one shell, including keystrokes and output.


```python
processes = sandbox.process.list(kind="pty", state="running")
session = next(info for info in processes if info.name and info.name.startswith("web-term-"))
print(f"{session.name}: {session.id} (cwd {session.cwd})")

# Attach to the web terminal session by its process id
handle = sandbox.pty.connect(session.id)
handle.stdin('echo "Hello from the SDK"\n')
```

- **`connect`** builds a handle without contacting the sandbox.
- An unknown or ended process ID fails on the first call that uses the handle.


```typescript
const processes = await sandbox.process.list({ kind: 'pty', state: 'running' })
const session = processes.items.find((info) => info.name?.startsWith('web-term-'))
if (!session) throw new Error('no web terminal session')
console.log(`${session.name}: ${session.id} (cwd ${session.cwd})`)

// Attach to the web terminal session by its process id
const handle = sandbox.pty.connect(session.id)
const connection = await handle.attach()
connection.write('echo "Hello from the SDK"\n')
```

- **`connect`** builds a handle without contacting the sandbox.
- An unknown process ID fails when **`attach`** is called.
- For a process that has already ended, **`attach`** resolves and the connection closes without output.
- **`attach`** needs a global **`WebSocket`** class.


```bash
# List running PTY processes; web terminal sessions are named web-term-<n>
daytona sandbox process list {sandboxId} --kind pty --state running

# A live session can also be fetched by name
daytona sandbox process get {sandboxId} web-term-1

# Attach to a web terminal session
daytona sandbox process attach {sandboxId} web-term-1
```

- **`attach`** uses raw mode, so **`Ctrl+C`** goes to the remote shell, not the CLI.
- **`attach`** returns when the shell ends.
- Running **`exit`** ends the shell for the browser tab too.


```bash
# List running PTY processes; web terminal sessions are named web-term-<n>
curl 'https://toolbox.daytona.com/toolbox/{sandboxId}/processes?kind=pty&state=running' \
  --header 'Authorization: Bearer <API_KEY>'

# A live session can also be fetched by name
curl 'https://toolbox.daytona.com/toolbox/{sandboxId}/processes/web-term-1' \
  --header 'Authorization: Bearer <API_KEY>'
```


:::note
Stopping or restarting a sandbox ends all of its shell processes. After the sandbox is running again, the **Terminal** tab starts with a fresh session.
:::

## Security

Terminal access is restricted to authenticated members of your [organization](https://www.daytona.io/docs/en/v2/organizations.md) whose [project API key](https://www.daytona.io/docs/en/v2/api-keys.md) holds the sandbox write permission. Members without this permission do not see the Terminal, Files, Desktop, or SSH tabs, and the terminal icon is hidden in the sandbox list. The terminal is served through the toolbox proxy, which authenticates every request with the project API key; making a [preview endpoint](https://www.daytona.io/docs/en/v2/preview.md) public does not expose the terminal.

:::caution[Warning]
The web terminal provides full shell access to your sandbox. Grant the sandbox write permission only to members who should be able to run arbitrary commands in your sandboxes.
:::