refac
Some checks are pending
Build Docker Image / build (linux/amd64, map[file:Dockerfile.slim name:slim short_tag:slim suffix:-slim]) (push) Waiting to run
Build Docker Image / build (linux/amd64, map[file:Dockerfile name:default short_tag:latest suffix:]) (push) Waiting to run
Build Docker Image / build (linux/amd64, map[file:Dockerfile.alpine name:alpine short_tag:alpine suffix:-alpine]) (push) Waiting to run
Build Docker Image / build (linux/arm64, map[file:Dockerfile name:default short_tag:latest suffix:]) (push) Waiting to run
Build Docker Image / build (linux/arm64, map[file:Dockerfile.alpine name:alpine short_tag:alpine suffix:-alpine]) (push) Waiting to run
Build Docker Image / build (linux/arm64, map[file:Dockerfile.slim name:slim short_tag:slim suffix:-slim]) (push) Waiting to run
Build Docker Image / merge (map[name:alpine short_tag:alpine suffix:-alpine]) (push) Blocked by required conditions
Build Docker Image / merge (map[name:default short_tag:latest suffix:]) (push) Blocked by required conditions
Build Docker Image / merge (map[name:slim short_tag:slim suffix:-slim]) (push) Blocked by required conditions

This commit is contained in:
Timothy Jaeryang Baek 2026-06-22 17:02:02 +02:00
parent 811d4abc18
commit 68f0fa1cf5
3 changed files with 39 additions and 7 deletions

View file

@ -133,6 +133,7 @@ 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]
@ -144,6 +145,21 @@ You can also point to a specific config file:
open-terminal run --config /path/to/my-config.toml
```
### 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.
## Using with Open WebUI
Open Terminal integrates with [Open WebUI](https://github.com/open-webui/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:

View file

@ -164,7 +164,7 @@ OPEN_TERMINAL_INFO = os.environ.get(
FILE_BROWSER_ROOT = os.environ.get(
"OPEN_TERMINAL_FILE_BROWSER_ROOT",
config.get("file_browser_root", "home"),
).strip().lower()
).strip()
# How long (in seconds) to keep per-session cwd entries in memory.
# Sliding window — refreshed on every access.
@ -174,4 +174,3 @@ SESSION_CWD_TTL: float = float(
config.get("session_cwd_ttl", 604_800), # 7 days
)
)

View file

@ -146,6 +146,25 @@ def get_filesystem(request: Request) -> UserFS:
return UserFS(username=username, home=home)
def get_file_browser_root(fs: UserFS) -> dict[str, str] | None:
configured = FILE_BROWSER_ROOT.strip()
mode = configured.lower()
if mode in ("", "home"):
return {"path": fs.home, "label": "Home"}
if mode == "filesystem":
return None
path = configured.replace("{{home}}", fs.home)
if path == "~":
path = fs.home
elif path.startswith("~/"):
path = os.path.join(fs.home, path[2:])
root_path = fs.resolve_path(path)
label = "Home" if root_path == fs.home else os.path.basename(root_path) or root_path
return {"path": root_path, "label": label}
app = FastAPI(
title="Open Terminal",
description="A remote terminal API.",
@ -445,11 +464,9 @@ async def get_cwd(
"cwd": _get_session_cwd(session_id, fs),
"home": fs.home,
}
if FILE_BROWSER_ROOT != "filesystem":
response["root"] = {
"path": fs.home,
"label": "Home",
}
root = get_file_browser_root(fs)
if root:
response["root"] = root
return response