2026-10-19 03:42:59 +09:00
2026-09-06 17:36:00 -04:00
2026-10-19 03:42:59 +09:00
2026-02-14 19:36:16 -06:00
2026-02-12 13:10:52 -06:00
2026-10-16 14:25:49 +04:00
2026-02-12 13:10:52 -06:00
2026-08-27 14:08:59 -04:00
2026-06-23 00:08:59 +02:00
2026-06-23 00:08:59 +02:00
2026-03-30 19:56:58 -05:00
2026-02-12 13:45:59 -06:00
2026-10-16 14:25:49 +04:00
2026-10-19 03:33:37 +09:00

⚡ Open Terminal

A lightweight, self-hosted terminal that gives AI agents and automation tools a dedicated environment to run commands, manage files, and execute code — all through a simple API.

Why Open Terminal?

AI assistants are great at writing code, but they need somewhere to run it. Open Terminal is that place — a remote shell with file management, search, and more, accessible over a simple REST API.

You can run it two ways:

  • Docker (sandboxed) — runs in an isolated container with a full toolkit pre-installed: Python, Node.js, git, build tools, data science libraries, ffmpeg, and more. Great for giving AI agents a safe playground without touching your host system.
  • Bare metal — install it with pip and run it anywhere Python runs. Commands run directly on your machine with access to your real files, your real tools, and your real environment, perfect for local development, personal automation, or giving an AI assistant full access to your actual projects.

Getting Started

docker run -d --name open-terminal --restart unless-stopped -p 8000:8000 -v open-terminal:/home/user -e OPEN_TERMINAL_API_KEY=your-secret-key ghcr.io/open-webui/open-terminal

That's it — you're up and running at http://localhost:8000.

Tip

If you don't set an API key, one is generated automatically. Grab it with docker logs open-terminal.

Image Variants

latest slim alpine openshift
Best for AI agent sandboxes Production / hardened Edge / CI / minimal footprint OpenShift restricted SCC
Size ~4 GB ~430 MB ~230 MB ~430 MB
Bundled tooling Node.js, gcc, ffmpeg, LibreOffice, LaTeX, Docker CLI, data science libs git, curl, jq git, curl, jq git, curl, jq
Install packages at runtime ✔ (has sudo) ✘ ✘ ✘
Multi-user mode ✔ ✘ ✘ ✘
Egress firewall ✔ ✔ ✔ ✘

slim and alpine have the same feature set. Slim uses Debian (glibc) for broader binary compatibility; Alpine uses musl libc and is smaller, but some C-extension pip packages may need to compile from source.

docker run -d -p 8000:8000 -e OPEN_TERMINAL_API_KEY=secret ghcr.io/open-webui/open-terminal:slim
docker run -d -p 8000:8000 -e OPEN_TERMINAL_API_KEY=secret ghcr.io/open-webui/open-terminal:alpine
docker run -d -p 8000:8000 -e OPEN_TERMINAL_API_KEY=secret ghcr.io/open-webui/open-terminal:openshift

Note

Slim and Alpine don't support OPEN_TERMINAL_PACKAGES / OPEN_TERMINAL_PIP_PACKAGES / OPEN_TERMINAL_NPM_PACKAGES. To add packages, extend Dockerfile.slim or Dockerfile.alpine.

Note

The default latest image includes LibreOffice for Word, Excel, and PowerPoint to PDF conversions. The slim, alpine, and openshift images stay minimal; build a custom image if those variants need Office conversion tools.

Note

The OpenShift image is for restricted non-root pod policies. It does not support runtime package installs, Docker socket access, the iptables egress firewall, or OPEN_TERMINAL_MULTI_USER=true. Build a custom image ahead of time when OpenShift users need extra tools.

Updating

docker pull ghcr.io/open-webui/open-terminal
docker rm -f open-terminal

Then re-run the docker run command above.

Bare Metal

No Docker? No problem. Open Terminal is a standard Python package:

# One-liner with uvx (no install needed)
uvx open-terminal run --host 0.0.0.0 --port 8000 --api-key your-secret-key

# Or install globally with pip
pip install open-terminal
open-terminal run --host 0.0.0.0 --port 8000 --api-key your-secret-key

Caution

On bare metal, commands run directly on your machine with your user's permissions. Use Docker if you want sandboxed execution.

Customizing the Docker Environment

The easiest way to add extra packages is with environment variables — no fork needed:

docker run -d --name open-terminal -p 8000:8000 \
  -e OPEN_TERMINAL_PACKAGES="cowsay figlet" \
  -e OPEN_TERMINAL_PIP_PACKAGES="httpx polars" \
  -e OPEN_TERMINAL_NPM_PACKAGES="typescript tsx" \
  ghcr.io/open-webui/open-terminal
Variable Description
OPEN_TERMINAL_PACKAGES Space-separated list of apt packages to install at startup
OPEN_TERMINAL_PIP_PACKAGES Space-separated list of pip packages to install at startup
OPEN_TERMINAL_NPM_PACKAGES Space-separated list of npm packages to install globally at startup

Note

Packages are installed each time the container starts, so startup will take longer with large package lists. For heavy customization, build a custom image instead.

Docker Access

The image includes the Docker CLI, Compose, and Buildx. To let agents build images, run containers, etc., mount the host's Docker socket:

docker run -d --name open-terminal -p 8000:8000 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v open-terminal:/home/user \
  ghcr.io/open-webui/open-terminal

Caution

Mounting the Docker socket gives the container full control over the host's Docker daemon, which is effectively root access on the host machine. Anyone with access to the terminal can pull/run arbitrary containers (including --privileged ones), mount host directories, access host networking, and manage all containers on the host. Only do this in fully trusted environments.

For full control, fork the repo, edit the Dockerfile, and build your own image:

docker build -t my-terminal .
docker run -d --name open-terminal -p 8000:8000 my-terminal

Configuration

Open Terminal can be configured via a TOML config file, environment variables, and CLI flags. Settings are resolved in this order (highest priority wins):

  1. CLI flags (--host, --port, --api-key, etc.)
  2. Environment variables (OPEN_TERMINAL_API_KEY, etc.)
  3. User config — $XDG_CONFIG_HOME/open-terminal/config.toml (defaults to ~/.config/open-terminal/config.toml)
  4. System config — /etc/open-terminal/config.toml
  5. Built-in defaults

Create a config file at either location with any of these keys (all optional):

host = "0.0.0.0"
port = 8000
api_key = "sk-my-secret-key"
cors_allowed_origins = "*"
log_dir = "/var/log/open-terminal"
binary_mime_prefixes = "image,audio"
execute_timeout = 5  # seconds to wait for command output (unset by default)
file_browser_root = "home"

Tip

Use the system config at /etc/open-terminal/config.toml to set site-wide defaults for host and port, and the user config for personal settings like the API key — this keeps the key out of ps / htop.

You can also point to a specific config file:

open-terminal run --config /path/to/my-config.toml

Memory and execution budgets

File downloads and proxy traffic stream in chunks. Uploads and generated ZIP/PDF files use temporary files, removed on completion or cancellation. Command logs rotate on disk without reading the whole log into memory.

Text and log reads return bounded pages. When truncated is true, continue text reads from next_line or log reads from next_offset. Explicit log tail reads return the newest output and can skip older entries. Download a file through /files/view when you need its complete original bytes.

These settings accept positive integers, through TOML keys or the corresponding OPEN_TERMINAL_ environment variable (for example, OPEN_TERMINAL_MAX_RESPONSE_BYTES):

TOML key Default Scope
max_response_bytes 1048576 Text/log content per page and notebook output budget
max_request_bytes 2097152 Ordinary HTTP request bodies
max_transfer_bytes 1073741824 Upload/proxy request bodies and uncompressed ZIP input
max_command_seconds 3600 Background command lifetime; separate from the output wait timeout
worker_memory_bytes 536870912 Linux address-space limit for document workers only

Commands, notebook sessions, and HTTP requests have no global concurrency cap. Oversized inputs return 413. JSON bodies are also checked for excessive nesting/object counts before parsing. Background commands that exceed their deadline stop with an error in their status response. Log I/O failures are reported there too; output is still drained and the command's completion state is finalized.

Directory scans examine at most 10,000 entries; content search scans at most 32 MiB, returns bounded snippets, and skips lines longer than 64 KiB. Narrow the search path when it exceeds these budgets. Text editing is limited to the text response budget and 50,000 lines. Text reads reject individual lines longer than 64 KiB. Document extraction allows up to 16 MiB of input/expanded ZIP content, 2 million extracted characters, and 100,000 spreadsheet cells. Two document workers may run concurrently, with a 60-second deadline and bounded output; additional document work returns HTTP 429. Limits are per server process; additional server workers multiply them.

Notebook kernels are stopped on cancelled execution, excessive output, or failed startup, and idle sessions expire after 30 minutes. Ordinary Python cell errors preserve the session. Unattached terminals expire after 60 seconds; connected terminals remain available until they disconnect, exit, or are deleted. Terminal I/O uses backpressure; Open Terminal does not override Uvicorn's WebSocket message size or queue settings.

Arbitrary shell/notebook code needs OS-level isolation to keep its allocations from exhausting the API container. On Linux, OPEN_TERMINAL_WORKLOAD_CGROUP can point to an existing, writable cgroup v2 directory with a finite memory.max. Launched commands, terminals, kernels, and document workers join that group before executing; keep the API outside it. Configure an aggregate memory budget that leaves room for the API, plus pids.max and memory.swap.max as appropriate. The host/container supervisor must delegate that cgroup and grant access to the worker users; Open Terminal does not create or modify host cgroups. Without it, application budgets do not bound arbitrary child allocations or forks. A memory limit on the entire container alone can still kill the API. The document address-space limit is Linux-only; macOS and Windows retain the application budgets but require platform isolation for hard workload memory limits.

File Browser Root

Open Terminal reports file-browser root metadata from GET /files/cwd so clients can hide parent navigation above a friendly starting point.

Set OPEN_TERMINAL_FILE_BROWSER_ROOT to:

Value Behavior
home Default. Report the current user's home directory as Home
/workspace Report an explicit path as the visual root
{{home}}/project Report a path under the current user's home
filesystem Opt out and report no visual root metadata

This is a UI hint for clients. It does not restrict terminal commands or file APIs.

External Workspace Storage

Open Terminal uses the filesystem it is mounted on. To store workspace files externally, mount that storage into the container:

  • Single-user: /home/user
  • Multi-user: /home

This can be a Docker volume, Kubernetes persistent volume, NFS/Azure Files mount, or FUSE mount such as blobfuse, s3fs, or rclone.

Office Previews

GET /files/view?path=... always returns the original file by default. Clients that want a rendered preview can add preview=true; when LibreOffice is available the server can return DOCX and PPTX previews as PDF. When rendered preview support is not available, the same endpoint falls back to returning the original file bytes.

Using with Open WebUI

Open Terminal integrates with Open WebUI, giving your AI assistants the ability to run commands, manage files, and interact with a terminal right from the AI interface. Make sure to add it under Open Terminal in the integrations settings, not as a tool server. Adding it as an Open Terminal connection gives you a built-in file navigation sidebar where you can browse directories, upload, download, and edit files. There are two ways to connect:

Direct Connection

Users can connect their own Open Terminal instance from their user settings. This is useful when the terminal is running on their local machine or a network only they can reach, since requests go directly from the browser.

  1. Go to User Settings → Integrations → Open Terminal
  2. Add the terminal URL and API key
  3. Enable the connection

System-Level Connection (Multi-User)

Admins can configure Open Terminal connections for all their users from the admin panel. No additional services required. Multiple terminals can be set up with access controlled at the user or group level. Requests are proxied through the Open WebUI backend, so the terminal only needs to be reachable from the server.

  1. Go to Admin Settings → Integrations → Open Terminal
  2. Add the terminal URL and API key
  3. Enable the connection

Built-in Multi-User Mode

Caution

Multi-user mode separates workspaces. It does not create a security boundary between users, and it is not designed for production multi-user deployments. Everyone shares one container: one kernel, one process list, one network stack, one temp directory. Users can watch each other's running commands, reach ports other users open, exhaust CPU, memory and disk for everyone, and interfere with shared system state. Provisioning accounts requires elevated privileges inside the container, so a user who sets out to reach root inside that container will find a way. Run this mode only where every user on the instance is trusted at the same level, and give each user their own instance whenever that trust does not hold. See SECURITY.md for how reports about this mode are handled.

For small, trusted deployments you can give each user their own workspace inside a single container:

docker run -d --name open-terminal -p 8000:8000 \
  -v open-terminal:/home \
  -e OPEN_TERMINAL_MULTI_USER=true \
  -e OPEN_TERMINAL_API_KEY=your-secret-key \
  ghcr.io/open-webui/open-terminal

Each user automatically gets a dedicated Linux account with its own home directory, so files, commands, and terminals stay in their own workspace and users do not walk over each other's work. Standard Unix permissions keep the workspaces apart in day-to-day use. They do not protect users from each other, and they are not meant to.

API Docs

Full interactive API documentation is available at http://localhost:8000/docs once your instance is running.

Star History

Star History Chart

Tip

Need real isolation between users? Terminals provisions and manages a separate Open Terminal container per user, with its own files, processes, resource limits and network boundary. That is the setup to use when users must be protected from each other. Terminals requires an Open WebUI Enterprise License for production use, see the Terminals documentation for deployment and licensing details. Built-in multi-user mode (OPEN_TERMINAL_MULTI_USER=true) only gives each user their own workspace inside one shared container.

License

MIT — see LICENSE for details.

Languages
Python 91.2%
Shell 4.5%
JavaScript 2%
Slim 1.4%
Dockerfile 0.9%